2017-01-03 79 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,你是對的,我不知道我發生了什麼事,那一刻,謝謝你的回覆。 –

相關問題