如何在不均匀间隔的数据上使用data.table计算R中的滚动统计量

时间:2014-03-26 00:11:03

标签: r data.table

我有一个由两个ID变量(一个嵌套在另一个中)和日期索引的数据集,我希望计算此数据中的滚动统计量。

我的真实数据集很大(约200万行),我喜欢使用data.table来提高其他任务的速度...但我无法找到一种最佳使用data.table的方法(即利用二进制搜索并避免矢量扫描)在这个问题。

示例数据:

set.seed(3)
dt1 <- 
 data.table(id1=c(rep("a",124),rep("b",124)),
            id2=c(rep("x",62),rep("y",62)),
            date=seq(as.Date("2012-05-01"),as.Date("2012-07-01"),"days"),
            var1=rpois(124,14),
            var2=rpois(124,3))
setkey(dt1,id1,id2,date)
# create uneven time spacing
dt1 <- dt1[-c(5,10,36,46,58)]

我的最终目标是计算id1 / id2中每一天的“滚动统计”,即:

和(VAR2)/ SUM(VAR1)

包括具有相同id1 / id2组合的所有其他行,并且在该行之前的30天内。

我不确定这是一个很好的第一步,但为了清楚起见,这里是为日期= 2012-06-12获取所有ID所需结果的代码:

dt1[date < as.Date("2012-06-12") & date > as.Date("2012-06-12")-31,
    list("newstat"=sum(var1)/sum(var2),
         "date"=as.Date("2012-06-12")),by=list(id1,id2)]

   id1 id2 newstat       date
1:   a   x   3.925 2012-06-12
2:   a   y   4.396 2012-06-12
3:   b   x   3.925 2012-06-12
4:   b   y   4.396 2012-06-12

我想过尝试在id1和id2上进行笛卡尔自连接,然后将生成的data.table减少到适当的日期范围(我不知道如何在一步中完成)。这给了我想要的结果,但是,我不知道如何在不使用逻辑子集作为减法步骤的i的参数的情况下这样做,这是不可接受的慢。我想我当时没有利用data.table的键,但不知道如何解决这个问题......

示例:

dt1[setkey(dt1[,list(id1,id2,"date_grp"=date)],id1,id2),
    list(date_grp,date,var1,var2)][
      # Here comes slow subset
      date<date_grp & date > date_grp-30,
      list("newstat"=sum(var1)/sum(var2)),
      by=list(id1,id2,date_grp)]

结果:

     id1 id2   date_grp newstat
  1:   a   x 2012-05-02  0.4286
  2:   a   x 2012-05-03  0.4000
  3:   a   x 2012-05-04  0.2857
  4:   a   x 2012-05-06  0.2903
  5:   a   x 2012-05-07  0.3056
 ---                           
235:   b   y 2012-06-27  0.2469
236:   b   y 2012-06-28  0.2354
237:   b   y 2012-06-29  0.2323
238:   b   y 2012-06-30  0.2426
239:   b   y 2012-07-01  0.2304

1 个答案:

答案 0 :(得分:7)

我确信有更好的方法可以做到这一点,但你可以做的一件事是避免完全笛卡尔联接,这就是通过生成带连接键的临时表来杀死你的行为:

dt.dates <- dt1[, list(date.join=seq(as.Date(date - 1, origin="1970-01-01"), by="-1 day", len=30)), by=list(date, id1, id2)]

对于每个date-id组,我们现在已生成允许的加入日期列表。现在我们加入数据并计算我们的指标。

setkey(dt.dates, date.join, id1, id2)
setkey(dt1,date,id1,id2)
dt.dates[dt1][ , sum(var1)/sum(var2), by=list(id1, id2, date)]

我无法复制你的结果6/12,但我认为我们有播种问题。比较:

> dt.date.join[dt1][ , sum(var1)/sum(var2), by=list(id1, id2, date)][date=="2012-06-12"]
   id1 id2       date       V1
1:   a   x 2012-06-12 3.630631
2:   a   y 2012-06-12 4.434783
3:   b   x 2012-06-12 3.634783
4:   b   y 2012-06-12 4.434783
> dt1[date < as.Date("2012-06-12") & date > as.Date("2012-06-12")-31, list("newstat"=sum(var1)/sum(var2), "date"=as.Date("2012-06-12")),by=list(id1,id2)]
   id1 id2  newstat       date
1:   a   x 3.630631 2012-06-12
2:   a   y 4.434783 2012-06-12
3:   b   x 3.634783 2012-06-12
4:   b   y 4.434783 2012-06-12

基本上是相同的结果。