2016-09-22 61 views
3

我們有交易彙總交易履行滑動窗口的標準

set.seed(1) 
X <- data.table(id = 1:10, 
       time = c(1,2,5,6,9,12,14,20,21,23), 
       val = sample(0.1*10^(1:4), 10, replace=TRUE), 
       code = sample(c('A','A','C','B'), 10, replace=TRUE) 
       ) 


    id time val code 
1: 1 1 10 A 
2: 2 2 10 A 
3: 3 5 100 C 
4: 4 6 1000 A 
5: 5 9 1 B 
6: 6 12 1000 A 
7: 7 14 1000 C 
8: 8 20 100 B 
9: 9 21 100 A 
10: 10 23 1 B 

對於每一行我想用val對於以前行,其中previous_row$time >= current_row$time - 3 即總和一起算code == 'A'出現的表預期的結果應該是

id time val code count_A_within_3 sum_a_within_3 
1: 1 1 10 A    1    10 
2: 2 2 10 A    2    20 
3: 3 5 100 C    1    10 
4: 4 6 1000 A    1   1000 
5: 5 9 1 B    1   1000 
6: 6 12 1000 A    1   1000 
7: 7 14 1000 C    1   1000 
8: 8 20 100 B    0    0 
9: 9 21 100 A    1   100 
10: 10 23 1 B    1   100 

這是可以計算出有效地利用data.tabledplyr

真實數據集包含〜1M組,其中應在每個組內執行此操作。每組中的行數範圍從1到1000.一個命令性的解決方案(用於嵌套ifs和狀態變量的循環)是可行的,但非常緩慢。

回答

2

採用非等距從最新的開發人員版本(1.9.7+)聯接:

X[, prev.time := time - 3] 

X[, c("count_A_within_3", "sum_a_within_3") := 
     X[X, on = .(time >= prev.time, time <= time), 
     .(sum(code == "A"), sum(val[code == "A"])), by = .EACHI][, .(V1, V2)]] 
X 
# id time val code prev.time count_A_within_3 sum_a_within_3 
# 1: 1 1 10 A  -2    1    10 
# 2: 2 2 10 A  -1    2    20 
# 3: 3 5 100 C   2    1    10 
# 4: 4 6 1000 A   3    1   1000 
# 5: 5 9 1 B   6    1   1000 
# 6: 6 12 1000 A   9    1   1000 
# 7: 7 14 1000 C  11    1   1000 
# 8: 8 20 100 B  17    0    0 
# 9: 9 21 100 A  18    1   100 
#10: 10 23 1 B  20    1   100 

您可能希望與.SD的更加健壯的代碼來取代內部的兩個X的;爲了清楚/易於理解它的工作原理,我只將它保留爲X

+0

將重寫使用.SD刪除重複的「code =='A'」?現實世界問題有多種條件,例如「col_3%in%lookup_vector&col_4!= 123&(col_5,50,90)」 – Rickard

+0

如果你只有一個(複雜)條件,你可以隨時過濾它:'...:= X [your_complicated_condition;例如code ==「A」] [X,on = ...';另一個選擇是做'...,{cond = code ==「A」; 。(sum(cond),sum(val [cond]))},...' – eddi

+0

是否可以優化執行時間?簡單的條件(例如代碼==「A」)花費了大約70秒,但是在我的22M行1M組數據集上更復雜的條件是〜1小時。 – Rickard