2017-01-03 83 views
7

我有日期,邮编一个data.table和购买金额。创建基于另一列值的新的R 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。此栏应sumpurchaseAmount所有数值为zipcode内以前Xdate

编辑:每个建议正如弗兰克,这里是预期的输出:

  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

重新下方的评论,这就是为什么我们建议将发表您的输入和预期的输出都,所以很显然,如果一个答案读取的问题简单地达到预期的效果。以下是一些指导:http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/28481250#28481250现在编辑它还不算太晚。 – Frank

+1

感谢您的指导和编辑代码@Frank。我编辑了这个问题的输出结果,并阅读了这些小插曲,以便更好地理解您的解决方案。由于这是我在论坛上的第一个问题,所以我非常感谢您提供答案和建议的礼貌和有用的方式。 – Mantelimies

回答

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 

这将使用“非相等”的加入,有效地采取各行;在每行中找到符合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键入到加载了data.table包的R控制台中。

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

+0

谢谢你的回答。但是,结果不是我正在寻找的。第6行'new_col'中的值应该是30(11 + 19),而第5行中它的值应该是19.这也适用于前4行,因为在之前的10个“zip”中没有其他购买天。不幸的是,由于我是初学者,因此我无法立即理解您对代码所做的工作,因此我无法提供基于修改所写内容的解决方案。 – Mantelimies

+0

好的,谢谢你的额外信息。我编辑过,现在发现它也匹配那两行(尽管不幸的是,代码现在更复杂了)。 – Frank

-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) 

它的工作速度相当快。

+1

@Frank,你是对的,我不知道我发生了什么事,那一刻,谢谢你的回复。 –

相关问题