根据另一列中的值和分组创建新的r data.table列

时间:2017-01-03 19:00:48

标签: r data.table

我有data.table日期,邮政编码和购买金额。

library(data.table)
set.seed(88)
DT <- data.table(date = Sys.Date()-365 + sort(sample(1:100, 10)), 
zip = sample(c("2000", "1150", "3000"),10, replace = TRUE), 
purchaseAmount = sample(1:20, 10))  

这会创建以下内容:

    date       zip              purchaseAmount
 1: 2016-01-08 1150              5
 2: 2016-01-15 3000             15
 3: 2016-02-15 1150             16
 4: 2016-02-20 2000             18
 5: 2016-03-07 2000             19
 6: 2016-03-15 2000             11
 7: 2016-03-17 2000              6
 8: 2016-04-02 1150             17
 9: 2016-04-08 3000              7
10: 2016-04-09 3000             20

我想添加第四列earlierPurchases。对于sum中的上一个 x purchaseAmount,此列应date zipcode中的所有值。

编辑:根据Frank的建议,这是预期的输出:

          date  zip purchaseAmount new_col
 1: 2016-01-08 1150              5       5
 2: 2016-01-15 3000             15      15
 3: 2016-02-15 1150             16      16
 4: 2016-02-20 2000             18      18
 5: 2016-03-07 2000             19      19
 6: 2016-03-15 2000             11      30
 7: 2016-03-17 2000              6      36
 8: 2016-04-02 1150             17      17
 9: 2016-04-08 3000              7       7
10: 2016-04-09 3000             20      27

是否有data.table方法可以执行此操作,还是应该编写循环function

2 个答案:

答案 0 :(得分:11)

这似乎有效:

DT[, new_col := 
  DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1), 
    sum(purchaseAmount)
  , by=.EACHI ]$V1
]


          date  zip purchaseAmount new_col
 1: 2016-01-08 1150              5       5
 2: 2016-01-15 3000             15      15
 3: 2016-02-15 1150             16      16
 4: 2016-02-20 2000             18      18
 5: 2016-03-07 2000             19      19
 6: 2016-03-15 2000             11      30
 7: 2016-03-17 2000              6      36
 8: 2016-04-02 1150             17      17
 9: 2016-04-08 3000              7       7
10: 2016-04-09 3000             20      27

这使用“非equi”连接,有效地占据每一行;在on=表达式中查找每行符合我们条件的所有行;然后按行(by=.EACHI)求和。在这种情况下,非等连接可能不如某些滚动求和方法效率低。

工作原理。

要向data.table添加列,通常的语法是DT[, new_col := expression]。在这里,表达式实际上甚至可以在DT[...]之外工作。尝试单独运行它:

DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1), 
  sum(purchaseAmount)
, by=.EACHI ]$V1

您可以逐步简化此操作,直到它只是加入...

DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1), 
  sum(purchaseAmount)
, by=.EACHI ]
# note that V1 is the default name for computed columns

DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1)]
# now we're down to just the join

连接语法类似于x[i, on=.(xcol = icol, xcol2 < icol2)],如在加载了data.table包的R控制台中键入?data.table时打开的doc页面中所述。

要开始使用data.table,我建议您查看the vignettes。在那之后,这可能看起来更清晰。

答案 1 :(得分:-1)

我没有找到任何data.table解决方案,这就是我得到它的方式:

library(dplyr)
earlierPurchases <- vector()

for(i in 1:nrow(DT)) {
  temp <- dplyr::filter(DT, zip == zip[i] & date < date[i])
  earlierPurchases[i] <- sum(temp$purchaseAmount)
}

DT <- cbind(DT, earlierPurchases)

它运作得非常快。