我有一个不平衡的面板,其中每个 ID 和月份都有某些观察结果(变量 x)。我正在尝试计算 x 的 6 个月滚动平均值,但仅限每年三月。我知道使用 zoo
,我可以每次计算平均值,但我认为这在计算上是昂贵的。我有一个非常大的面板,所以最好先定义一个索引并将其传递给函数。另外,我的面板不平衡,因此有时我在给定的 3 月份拥有全部 6 个过去值,有时却没有。如果至少有 3 个可用值,我仍然想计算平均值。
这是一些示例代码和我迄今为止的解决方案:
library(data.table)
set.seed(1)
time=rep(seq(as.Date("2010-02-01"), length=42, by="1 month") - 1,2)
IDs=rep(letters[1:2],each=length(time))
DT <- data.table(time=time,
ID=IDs,
ind=rep(1:(2*length(time))),
row=1:(2*length(time)),
x=sample(2*length(time)))
DT
DT <- DT[!ind %in% c(11,12,26)]
DT
library(zoo)
DT[,movavg := if(length(x) >= 3){ rollapply(x, 6, sum, na.rm = FALSE,align = "right",fill = NA)}else{
rep(NA,length(x))
},by=ID]
DT
目标是简单地显示每个三月的相应移动平均值,其中包含过去 6 个观测值。我不介意是否保留原始面板,即仅显示三月份的结果,或者仅提取三月份的值而不显示其他内容。
我的代码可以工作,但它每行/每月都会进行计算。我想要它做的是仅在定义的索引上工作。问题是,由于面板不平衡,游行之间的距离并不相等。例如,一年到另一年可能是 12 个月,但下一年到下一年可能是 10 个月,遗憾的是缺少 2 个观测值。还可以使用roll apply
吗?任何有关数据表
或dplyr
的提示都将受到高度赞赏。
最佳答案
如果问题中的这段代码给出了您想要的内容
DT[,movavg := if(length(x) >= 3){ rollapply(x, 6, sum, na.rm = FALSE,align = "right",fill = NA)}else{
rep(NA,length(x))
},by=ID]
然后,第一个运行速度快了 2.8 倍,并给出了相同的结果,第二个使用 data.table 中的 frollsum 运行速度快了 4.8 倍。
DT[, movavg := rollsumr(x, 6, fill = NA), by = ID]
DT[, movavg := frollsum(x, 6), by = ID]
关于r - 移动平均线变化窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72276386/