我有一个data.table,其中包含一列客户ID,他们进行购买的天数列以及一个具有该购买价值的列。我想要做的是计算每个客户每天购买价值的平均值,用下一个可用值填充缺失值。
为简单起见,我在最小的例子中没有重复的日子。
library(data.table)
dat <- data.table(custid=rep(seq(10),5), day=sample(50), val=rnorm(50,0,1))[order(custid,day)]
现在,我知道如何解决这个问题,但我不知道如何有效地解决这个问题。一种解决方案是扩展data.table,使缺失值变为NA,然后使用na.locf()
中的zoo
向后进行下一次观察:
library(zoo)
res <- dat[as.data.table(expand.grid(custid=seq(10), day=seq(50))), on=c('custid','day'), allow.cartesian=TRUE, nomatch=NA][order(custid,day)]
res[, val:=na.locf(val, fromLast=TRUE, na.rm=FALSE), by='custid']
res <- res[,list(meanVal=mean(val, na.rm=TRUE)), by='day']
但是,当有很多天和很多客户时,这会创建一个非常大的表,但大多数客户只在极少数时间内购买。所以我不希望这样。
另一种解决方案是循环使用,每天过滤和聚合,然后再将行绑定到data.table中:
res2 <- list()
for (dy in seq(max(dat$day))) {
res2 <- c(res2,
list(dat[day>=dy, .SD[1], by='custid'][,list(day=dy, meanVal=mean(val, na.rm=T))]))
}
res2 <- rbindlist(res2)
然而,这很慢。
有没有人能想出一个既不需要慢速循环也不需要创建大型中间表的data.table解决方案?
答案 0 :(得分:3)
在我的有限测试中,这比你的任何一个选项都要快(顺便说一下使用<p-dialog header="Alert Dialog" [(visible)]="display" modal="modal" width="300" responsive="true">
<header>
Header content here
</header>
Content
<footer>
Footer content here
</footer>
</p-dialog>
而不是CJ
),并且不会占用太多内存:
data.table(expand.grid
这假设数据按日排序,如OP。