【问题标题】:Scatter plot kernel smoothing: ksmooth() does not smooth my data at all散点图内核平滑:ksmooth() 根本不平滑我的数据
【发布时间】:2016-10-23 11:54:12
【问题描述】:

原问题

我想平滑我的解释变量,比如车辆的速度数据,然后使用这个平滑值。我搜索了很多,没有找到直接是我的答案。

我知道如何计算核密度估计(density()KernSmooth::bkde()),但我不知道如何计算速度的平滑值。


重新编辑的问题

感谢@ZheyuanLi,我能够更好地解释我拥有什么以及我想做什么。所以我重新编辑了我的问题如下。

我在一段时间内对车辆进行了一些速度测量,存储为数据框vehicle

         t       speed
1        0   0.0000000
2        1   0.0000000
3        2   0.0000000
4        3   0.0000000
5        4   0.0000000
.        .           .
.        .           .
1031  1030   4.8772222
1032  1031   4.4525000
1033  1032   3.2261111
1034  1033   1.8011111
1035  1034   0.2997222
1036  1035   0.2997222

这是一个散点图:

我想平滑speedt,我想为此目的使用内核平滑。根据@Zheyuan的建议,我应该使用ksmooth()

fit <- ksmooth(vehicle$t, vehicle$speed)

但是,我发现平滑后的值与我的原始数据完全相同:

sum(abs(fit$y - vehicle$speed))  # 0

为什么会这样?谢谢!

【问题讨论】:

  • 假设你有一个向量,使用R中的density函数。你可以将它赋值为Y&lt;-density(Speed),得到Y$y,也就是平滑后的值。
  • rollmean in package zoo 很好。
  • loess 函数通常用于非参数平滑。它有一个预测方法。计算 kde 的平滑度对我来说没有多大意义。也许你应该发布一个例子。这从未排序的值开始,对它们进行排序并估计它们的本地“接近度”。
  • 其实我想从平滑的速度计算加速度,然后用它们构建另一个解释变量,然后做一个回归。
  • @ZheyuanLi:我发表评论并不意味着我也投反对票。事实上,我很少投反对票。我确实同意它现在很有用,并且您的第二个答案值得代表,尽管我认为有两个不同的答案有点令人困惑。

标签: r regression curve-fitting smoothing


【解决方案1】:

回答老问题


需要区分“核密度估计”和“核平滑”。

密度估计,仅适用于单个变量。它旨在估计该变量在其物理域上的分布程度。例如,如果我们有 1000 个正常样本:

x <- rnorm(1000, 0, 1)

我们可以通过核密度估计器来评估它的分布:

k <- density(x)
plot(k); rug(x)

x 轴上的地毯显示您的 x 值的位置,而曲线测量这些地毯的密度。

kernel smoother,其实是一个回归问题,或者说散点图的平滑问题。您需要两个变量:一个响应变量y,和一个解释变量x。让我们使用上面的x 作为解释变量。对于响应变量y,我们从

生成一些玩具值
y <- sin(x) + rnorm(1000, 0, 0.2)

鉴于yx 之间的散点图:

我们想找到一个平滑函数来逼近那些分散的点。

带有 R 函数 ksmooth() 的 Nadaraya-Watson 核回归估计将为您提供帮助:

s <- ksmooth(x, y, kernel = "normal")
plot(x,y, main = "kernel smoother")
lines(s, lwd = 2, col = 2)

如果你想用预测来解释一切:

  • 内核密度估计:给定x,预测x的密度;也就是说,我们估计了P(grid[n] &lt; x &lt; grid[n+1]) 的概率,其中grid 是一些网格点;
  • 内核平滑:给定x,预测y;也就是说,我们估计了函数f(x),它近似于y

在这两种情况下,您都没有解释变量 x 的平滑值。所以你的问题:“我想平滑我的解释变量”是没有意义的。


你真的有时间序列吗?

车辆的速度”听起来您正在监视speedt。如果是这样,获取speedt 之间的散点图,并使用ksmooth()

loess()smooth.spline() 等其他平滑方法不属于内核平滑类,但您可以比较。

【讨论】:

  • 非常感谢您的详细解释,这让我的问题变得如此清晰。是的没错,我有 1202 秒的速度数据,所以,根据你的回答,我应该使用 ksmooth(t, speed, ....) ?
  • 非常感谢您的帮助。我做了 ksmooth(t, speed),但结果和 Speed 原始值一样。
  • 我添加了时间、速度数据
  • 亲爱的哲元,我找到了,是带宽的问题,我改了,现在从ksmooth得到结果,再次感谢你的帮助。
【解决方案2】:

回答重新编辑的问题

ksmooth() 的默认带宽为 0.5:

 ksmooth(x, y, kernel = c("box", "normal"), bandwidth = 0.5,
         range.x = range(x),
         n.points = max(100L, length(x)), x.points)

对于滞后 1 的时间序列数据,这意味着在 (i-0.5, i+0.5) 的邻域中没有其他 speed 数据,对于时间 t = i,除了 speed[i]。结果,没有进行局部加权平均!

您需要选择更大的带宽。例如,如果我们希望平均超过 20 个值,我们应该设置 bandwidth = 10(不是 20,因为它是双面的)。这就是我们得到的:

fit <- ksmooth(vehicle$t, vehicle$speed, bandwidth = 10)
plot(vehicle, cex = 0.5)
lines(fit,col=2,lwd = 2)

平滑度选择

ksmooth() 的一个问题是您必须自己设置bandwidth。您可以看到该参数极大地塑造了拟合曲线。大bandwidth使曲线平滑,但远离数据;而小带宽则相反。

是否存在最佳bandwidth?有没有办法选择最好的?

是的,使用sm包中的sm.regression(),使用交叉验证方法选择带宽。

fit <- sm.regression(vehicle$t, vehicle$speed, method = "cv", eval.points = 0:1035)
## plot will be automatically generated!

您可以检查fit$h 是 18.7。

其他方法

也许您认为 sm.regression() 会过度平滑您的数据?好吧,使用loess(),或者我最喜欢的:smooth.spline()

我有一个答案:

在这里,我将演示smooth.spline()的用法:

fit <- smooth.spline(vehicle$t, vehicle$speed, all.knots = TRUE, control.spar = list(low = -2, hight = 2))

# Call:
# smooth.spline(x = vehicle$t, y = vehicle$speed, all.knots = TRUE, 
#     control.spar = list(low = -2, hight = 2))

# Smoothing Parameter  spar= 0.2519922  lambda= 4.379673e-11 (14 iterations)
# Equivalent Degrees of Freedom (Df): 736.0882
# Penalized Criterion: 3.356859
# GCV: 0.03866391

plot(vehicle, cex = 0.5)
lines(fit$x, fit$y, col = 2, lwd = 2)

或者使用它的回归样条版本:

fit <- smooth.spline(vehicle$t, vehicle$speed, nknots = 200)
plot(vehicle, cex = 0.5)
lines(fit$x, fit$y, col = 2, lwd = 2)

你真的需要阅读我上面的第一个链接,了解为什么我在第一种情况下使用control.spar,而在第二种情况下没有。

更强大的包

我肯定会推荐mgcv。关于mgcv,我有几个答案,但我不想让你不知所措。所以,我不会在这里做扩展。好好学习使用ksmooth()smooth.spline()loess()。以后遇到更复杂的问题,再来堆栈溢出求助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 2021-09-30
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 2020-03-11
    相关资源
    最近更新 更多