我希望平滑我的解释变量,例如车辆的速度数据,然后使用这个平滑的值。我搜索了很多,并没有发现任何直接是我的答案。
我知道如何计算核密度估算(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
这是散点图:
我希望speed
对t
进行平滑,我想为此目的使用内核平滑。根据@ Zheyuan的建议,我应该使用ksmooth()
:
fit <- ksmooth(vehicle$t, vehicle$speed)
但是,我发现平滑后的值与原始数据完全相同:
sum(abs(fit$y - vehicle$speed)) # 0
为什么会这样?谢谢!
答案 0 :(得分:10)
您需要区分核心密度估算&#34;和&#34;内核平滑&#34;。
密度估算,仅适用于单个变量。它旨在估计这个变量在物理领域的分布情况。例如,如果我们有1000个普通样本:
x <- rnorm(1000, 0, 1)
我们可以通过核密度估算器评估其分布:
k <- density(x)
plot(k); rug(x)
x轴上的地毯显示x
值的位置,而曲线则测量这些地毯的密度。
内核更平滑,实际上是回归问题,或散点图平滑问题。您需要两个变量:一个响应变量y
和一个解释变量x
。我们只需使用上面的x
作为解释变量。对于响应变量y
,我们从
y <- sin(x) + rnorm(1000, 0, 0.2)
考虑y
和x
之间的散点图:
我们希望找到一个平滑函数来近似那些散点。
Nadaraya-Watson核回归估计,R函数ksmooth()
将帮助您:
s <- ksmooth(x, y, kernel = "normal")
plot(x,y, main = "kernel smoother")
lines(s, lwd = 2, col = 2)
如果您想根据预测解释所有内容:
x
,预测x
的密度;也就是说,我们估算了概率P(grid[n] < x < grid[n+1])
,其中grid
是一些网格点; x
,预测y
;也就是说,我们估计函数f(x)
,它近似y
。在这两种情况下,您都没有解释变量x
的平滑值。所以你的问题是:&#34;我想要平滑我的解释变量&#34;毫无意义。
你真的有时间片吗?
&#34; 车辆的速度&#34;听起来好像你正在跟踪speed
时间t
。如果是,请在speed
和t
之间获取散点图,并使用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)
平滑度选择
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!
您可以检查fit$h
是否为18.7。
其他方法
也许您认为sm.regression()
过度平滑您的数据?好吧,使用loess()
或我最喜欢的:smooth.spline()
。
我有一个答案:
smooth.spline()
;这个非常技术性!smooth.spline()
;这是一个实用的建模。loess()
;这个是关于loess()
的一般用法。在这里,我将演示使用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()
。将来,当你遇到更复杂的问题时,回到堆栈溢出并寻求帮助!