我想计算某个时间窗口内的移动平均值,而不在时间序列开始时生成 NA。例如,如果我将时间窗口设置为 3,那么前 2 个观察值将具有 NA。我想要的是第一次观察的时间窗口为 1,第二次观察的时间窗口为 2,所有剩余的观察时间窗口为 3。
我当前的代码:
#example data
x <- c(3,9,2,8,4,6,5,8)
#moving average with time window of length 3
(ma3 <- filter(x,rep(1/3,3),sides=1))
我想计算某个时间窗口内的移动平均值,而不在时间序列开始时生成 NA。例如,如果我将时间窗口设置为 3,那么前 2 个观察值将具有 NA。我想要的是第一次观察的时间窗口为 1,第二次观察的时间窗口为 2,所有剩余的观察时间窗口为 3。
我当前的代码:
#example data
x <- c(3,9,2,8,4,6,5,8)
#moving average with time window of length 3
(ma3 <- filter(x,rep(1/3,3),sides=1))
除了蛮力,我没有看到其他方法:
使用rollapply
from packagezoo
而不是filter
:
c(x[1], mean(x[1:2]), rollapply(x, width=3, FUN=mean))
让我也跳上rollapply
火车:
> rollapply(c(NA, NA, x), width=3, FUN=mean, na.rm=T)
[1] 3.000000 6.000000 4.666667 6.333333 4.666667 6.000000 5.000000 6.333333
预先添加两个 = 3-1的NA
值并使用na.rm=T
具有扩展时间序列的效果,但忽略了计算平均值的新值。稍微困难但其他方面等效的语法
> rollapply(c(NA, NA, x), width=3, FUN=function(v) mean(v, na.rm=T))
感谢 Matthew 指出这一点。
@thelatemail 做得很好,但是他在代码中有一个错误(test[]
应该x[]
在函数内部替换),更重要的是他必须对向量的末尾做同样的事情(如果你想要 side=2)。此外,窗口大小应该是向量中第 i 个元素的两倍+1(最后是第 n 个元素)。所以,这是最终版本:
movavg.grow = function(x,window) {
startma = sapply(1:(floor(window/2)),function(y) mean(x[1:((y-1)*2+1)]))
endma = sapply(1:(floor(window/2)),function(y) mean(x[(length(x)-((y-1)*2)):length(x)]))
endma = rev(endma)
c(startma,
filter(x,rep(1/window,window))[(floor(window/2):(length(x)- floor(window)/2)+1)],
endma)
}
至于测试,你想要的必须1:10
返回x=1:10
> x=1:10
> x
[1] 1 2 3 4 5 6 7 8 9 10
> movavg.grow(x,5)
[1] 1 2 3 4 5 6 7 8 9 10
> movavg.grow(x,3)
[1] 1 2 3 4 5 6 7 8 9 10
您要求的功能称为“部分”窗口,AFAIK 已在 zoo 包中提供。
data.table中还有新的快速滚动均值函数将在1.12.0中发布。
不幸的是,它不支持部分窗口,但您可以通过以下方式使用该函数的“自适应”功能实现所需的行为:
x = c(3,9,2,8,4,6,5,8)
window = 3
library(data.table)
n = c(seq.int(window), rep(window, length(x)-window))
frollmean(x, n, adaptive=TRUE)
#[1] 3.000000 6.000000 4.666667 6.333333 4.666667 6.000000 5.000000 6.333333
您可以在网上找到新功能的手动输入?froll
。
使用移动平均线的大小在序列的开头和结尾添加零。这将防止 NA。
基础 R 中的自定义函数可让您到达那里:
movavg.grow <- function(x,window,sides) {
startma <- sapply(1:(window-1),function(y) mean(x[1:y]))
c(startma,filter(x,rep(1/window,window),sides=sides)[window:length(x)])
}
测试它:
> test <- c(3,9,2,8,4,6,5,8)
> movavg.grow(x=test,window=3,sides=1)
[1] 3.000000 6.000000 4.666667 6.333333 4.666667 6.000000 5.000000 6.333333