7

我想计算某个时间窗口内的移动平均值,而不在时间序列开始时生成 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))
4

6 回答 6

5

除了蛮力,我没有看到其他方法:

使用rollapplyfrom packagezoo而不是filter

c(x[1], mean(x[1:2]), rollapply(x, width=3, FUN=mean))
于 2013-02-17T22:12:17.343 回答
3

让我也跳上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 指出这一点。

于 2013-02-17T22:15:50.377 回答
2

@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
于 2014-04-20T02:41:53.790 回答
2

您要求的功能称为“部分”窗口,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

于 2018-12-22T15:31:18.573 回答
1

使用移动平均线的大小在序列的开头和结尾添加零。这将防止 NA。

于 2013-02-17T22:05:53.313 回答
1

基础 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
于 2013-02-17T22:58:01.247 回答