R data.table滑动窗口

使用data.table包实现滑动窗口函数的最佳(最快)方法是什么?

我试图计算滚动中位数,但每个date有多个行(由于2个额外的因素),我认为这意味着动物园rollapplyfunction将无法正常工作。 这是一个使用天真for循环的例子:

library(data.table) df <- data.frame( id=30000, date=rep(as.IDate(as.IDate("2012-01-01")+0:29, origin="1970-01-01"), each=1000), factor1=rep(1:5, each=200), factor2=1:5, value=rnorm(30, 100, 10) ) dt = data.table(df) setkeyv(dt, c("date", "factor1", "factor2")) get_window <- function(date, factor1, factor2) { criteria <- data.table( date=as.IDate((date - 7):(date - 1), origin="1970-01-01"), factor1=as.integer(factor1), factor2=as.integer(factor2) ) return(dt[criteria][, value]) } output <- data.table(unique(dt[, list(date, factor1, factor2)]))[, window_median:=as.numeric(NA)] for(i in nrow(output):1) { print(i) output[i, window_median:=median(get_window(date, factor1, factor2))] } 

data.table目前对于滚动窗口没有任何特殊的function。 在这里回答另一个类似的问题在这里进一步的细节:

有没有一种快速的方法来运行data.table内的滚动回归?

滚动中位数是有趣的。 它需要一个专门的function来做有效的工作(和之前的评论一样):

C中的滚动中值algorithm

这里的问题和答案data.table解决scheme都是非常低效的,相对于一个适当的专业rollingmedianfunction(这是不适用于R afaik)。

我设法通过创build一个滞后的数据集并做了一个巨大的连接,将示例降低到1.4s。

 df <- data.frame( id=30000, date=rep(as.IDate(as.IDate("2012-01-01")+0:29, origin="1970-01-01"), each=1000), factor1=rep(1:5, each=200), factor2=1:5, value=rnorm(30, 100, 10) ) dt2 <- data.table(df) setkeyv(dt, c("date", "factor1", "factor2")) unique_set <- data.table(unique(dt[, list(original_date=date, factor1, factor2)])) output2 <- data.table() for(i in 1:7) { output2 <- rbind(output2, unique_set[, date:=original_date-i]) } setkeyv(output2, c("date", "factor1", "factor2")) output2 <- output2[dt] output2 <- output2[, median(value), by=c("original_date", "factor1", "factor2")] 

在这个testing数据集上工作得很好,但是在我的真实testing数据集上,它却失败了8GB的内存。 我将尝试移动到其中一个高内存EC2实例(17,34或68GB内存)以使其工作。 任何想法如何以较less内存密集的方式做到这一点,将不胜感激

这个解决scheme的工作,但需要一段时间。

 df <- data.frame( id=30000, date=rep(seq.Date(from=as.Date("2012-01-01"),to=as.Date("2012-01-30"),by="d"),each=1000), factor1=rep(1:5, each=200), factor2=1:5, value=rnorm(30, 100, 10) ) myFun <- function(dff,df){ median(df$value[df$date>as.Date(dff[2])-8 & df$date<as.Date(dff[2])-1 & df$factor1==dff[3] & df$factor2==dff[4]]) } week_Med <- apply(df,1,myFun,df=df) week_Med_df <- cbind(df,week_Med)