散点图内核平滑:ksmooth()根本不会平滑我的数据

时间:2016-06-21 19:15:31

标签: r regression curve-fitting smoothing

原始问题

我希望平滑我的解释变量,例如车辆的速度数据,然后使用这个平滑的值。我搜索了很多,并没有发现任何直接是我的答案。

我知道如何计算核密度估算(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

这是散点图:

scatter

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

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

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

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

为什么会这样?谢谢!

2 个答案:

答案 0 :(得分:10)

回答旧问题

您需要区分核心密度估算&#34;和&#34;内核平滑&#34;。

密度估算,仅适用于单个变量。它旨在估计这个变量在物理领域的分布情况。例如,如果我们有1000个普通样本:

x <- rnorm(1000, 0, 1)

我们可以通过核密度估算器评估其分布:

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

density

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

内核更平滑,实际上是回归问题,或散点图平滑问题。您需要两个变量:一个响应变量y和一个解释变量x。我们只需使用上面的x作为解释变量。对于响应变量y,我们从

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

考虑yx之间的散点图:

scatter

我们希望找到一个平滑函数来近似那些散点。

Nadaraya-Watson核回归估计,R函数ksmooth()将帮助您:

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

ks

如果您想根据预测解释所有内容:

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

在这两种情况下,您都没有解释变量x的平滑值。所以你的问题是:&#34;我想要平滑我的解释变量&#34;毫无意义。

你真的有时间片吗?

&#34; 车辆的速度&#34;听起来好像你正在跟踪speed时间t。如果是,请在speedt之间获取散点图,并使用ksmooth()

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

答案 1 :(得分:5)

回答重新编辑的问题

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的时间序列数据,这意味着除了speed之外,(i-0.5, i+0.5)的时间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)

enter image description here

平滑度选择

ksmooth()的一个问题是,您必须自己设置bandwidth。您可以看到此参数极大地调整了拟合曲线。大bandwidth使曲线平滑,但远离数据;虽然小带宽反过来。

是否有最佳bandwidth?有没有办法选择最好的一个?

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

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

enter image description here

您可以检查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)

enter image description here

或使用其回归样条版本:

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

enter image description here

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

更强大的套餐

我肯定会推荐mgcv。我对mgcv有几个答案,但我不想压倒你。所以,我不会在这里做扩展。学习使用ksmooth()smooth.spline()loess()。将来,当你遇到更复杂的问题时,回到堆栈溢出并寻求帮助!