使用data.table包在R中对多个变量进行滚动平均。

13

我想为我拥有的每个数值变量计算滚动平均值。使用data.table软件包,我知道如何计算单个变量的值。但是,我应该如何修改代码,以便它可以一次处理多个变量,而不是修改变量名称并重复此过程多次?谢谢。

假设我还有其他名为“V2”、“V3”和“V4”的数值变量。

require(data.table)
setDT(data)
setkey(data,Receptor,date)
data[ , `:=` ('RollConc' = rollmean(AvgConc, 48, align="left", na.pad=TRUE)) , by=Receptor]

在此处可以找到我的样本数据副本: https://drive.google.com/file/d/0B86_a8ltyoL3OE9KTUstYmRRbFk/view?usp=sharing

我希望得到每个受体的“AvgConc”,“TotDep”,“DryDep”和“WetDep”的5小时滚动平均值。


请展示一些数据的例子。 - akrun
已上传示例数据。谢谢。 - Vicki1227
1
谢谢,但我有下载数据的限制。 有人会尝试吗? - akrun
谢谢!它运行得非常好。 - Vicki1227
有没有办法添加一个数字变量“事件”来标记每个受体的滚动均值计算?例如,对于受体1,第一个滚动均值将被标记为Event [1],最后一个滚动均值计算将被标记为Event [n]?对于受体2,滚动均值也将被标记为事件j在1到length [rollingmean]中。 - Vicki1227
嗨,Vicki,你介意分享一下测试数据吗?我想多学习一些。 - Grec001
3个回答

20

根据您的描述,您想要类似于这样的东西,这类似于在data.table文献中找到的一个示例:

library(data.table)
set.seed(42)
DT <- data.table(x = rnorm(10), y = rlnorm(10), z = runif(10), g = c("a", "b"), key = "g")
library(zoo)
DT[, paste0("ravg_", c("x", "y")) := lapply(.SD, rollmean, k = 3, na.pad = TRUE), 
   by = g, .SDcols = c("x", "y")]

另外一个问题...我看到代码计算了我的数据,但结果没有保存为变量...我该如何将这些滚动平均值保存为新的数据框中的变量? - Vicki1227
我不明白。它们已保存为data.table的列。你为什么想要它们在另一个data.table中?如果必须这样做,你可以始终对data.table进行子集操作。 - Roland
未来可以通过实现data.table#626来改进。 - jangorecki
有没有办法添加数字变量“事件”来标记每个受体的滚动平均计算?例如,对于受体1,第一个滚动平均将被标记为Event[1],而计算的最后一个滚动平均将是Event[n]?对于受体2,同样,滚动平均也将被标记为Event j在1到length[rollingmean]的范围内。 - Vicki1227

13

现在,可以使用data.table包中的frollmean函数来实现这一点。

library(data.table)    
xy <- c("x", "y")
DT[, (xy):= lapply(.SD, frollmean, n = 3, fill = NA, align="center"), 
                                   by = g, .SDcols =  xy]

在这里,我将通过滚动平均值替换x和y列。


# Data
set.seed(42)
DT <- data.table(x = rnorm(10), y = rlnorm(10), z = runif(10), 
                                g = c("a", "b"), key = "g")

1
这个答案并不是最优的,没有必要使用 lapply,直接使用 frollmean(.SD, ...) 即可。它是向量化的,速度会更快。 - jangorecki

1
尽管我的评论早就发表了,克里夫仍然没有更正他的答案,因此没有正确使用向量化参数在frollmean中提交。
DT[, paste0("r_", vars) := frollmean(.SD, n=w, align=align), by = g, .SDcols = vars]

一个基准
library(data.table)
set.seed(42)
n = 1e6
DT = data.table(V1 = rnorm(n), V2 = rlnorm(n), V3 = runif(n), g = rep(c("a","b"),n/2), key="g")
vars = c("V1","V2","V3")
library(zoo)
w = 48
align = "left"

roland = function(DT) DT[, paste0("r_", vars) := lapply(.SD, rollmean, k=w, na.pad=TRUE, align=align), by = g, .SDcols = vars]
cliff = function(DT) DT[, paste0("r_", vars) := lapply(.SD, frollmean, n=w, fill=NA, align=align), by = g, .SDcols = vars]                                   
jan = function(DT) DT[, paste0("r_", vars) := frollmean(.SD, n=w, align=align), by = g, .SDcols = vars]

DT1 = copy(DT)
DT2 = copy(DT)
DT3 = copy(DT)
system.time(a1 <- roland(DT1))
#   user  system elapsed 
#  0.776   0.079   0.774
system.time(a2 <- cliff(DT2))
#   user  system elapsed 
#  0.102   0.000   0.029 
system.time(a3 <- jan(DT3))
#   user  system elapsed 
#  0.064   0.000   0.023

all.equal(DT1, DT2)
#[1] TRUE
all.equal(DT1, DT3)
#[1] TRUE

最重要的是,变量越多,计算速度越快,因为它们可以并行计算。
如果我们扩大数据集并从基准测试中去除`.data.table`的开销,这一点很容易观察到。
library(data.table)
set.seed(42)
n = 1e7
nth = 8
DT = as.data.table(replicate(nth, rnorm(n)))
setDTthreads(nth)
w = 48
align = "left"
DT2 = copy(DT)
DT3 = copy(DT)

system.time(a2 <- lapply(DT2, frollmean, n=w, align=align))
#   user  system elapsed 
#  0.316   0.244   0.561 
system.time(a3 <- frollmean(DT2, w, align=align))
#   user  system elapsed 
#  1.064   0.357   0.183 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接