2016-12-12 37 views
4

我有一個相當大的數據集,我對基於來自另一列的值向前推進的「向前邁進」值感興趣。例如,如果我有一個Value = 3Time = 0和一個DesiredShift = 2,我希望3下移兩行爲Time = 2。這是一個可重現的例子。在另一列中將行值按滯後值移位

生成可再現的假數據

library(data.table) 
set.seed(1) 
rowsPerID <- 8 
dat <- CJ(1:2, 1:rowsPerID) 
setnames(dat, c("ID","Time")) 
dat[, Value := rpois(.N, 4)] 
dat[, Shift := sample(0:2, size=.N, replace=TRUE)] 

假數據

#  ID Time Value Shift 
# 1: 1 1  3  2 
# 2: 1 2  3  2 
# 3: 1 3  4  1 
# 4: 1 4  7  2 
# 5: 1 5  2  2 
# 6: 1 6  7  0 
# 7: 1 7  7  1 
# 8: 1 8  5  0 
# 9: 2 1  5  0 
# 10: 2 2  1  1 
# 11: 2 3  2  0 
# 12: 2 4  2  1 
# 13: 2 5  5  2 
# 14: 2 6  3  1 
# 15: 2 7  5  1 
# 16: 2 8  4  1 

我希望每個Value前移根據所述Shift柱。因此第3行的 DesiredOutput列將等於3,因爲Time=1的值爲 Value = 3Shift = 2

行4示出了3 + 4 = 7,因爲3個向下移位2個4向下移位1

我想能夠通過ID組做到這一點和data.table希望利用 因爲速度的對這個問題感興趣。

所需的結果

#  ID Time Value Shift DesiredOutput 
# 1: 1 1  3  2  NA 
# 2: 1 2  3  2  NA 
# 3: 1 3  4  1  3 
# 4: 1 4  7  2  3+4 = 7 
# 5: 1 5  2  2  NA 
# 6: 1 6  7  0  7+7 = 14 
# 7: 1 7  7  1  2 
# 8: 1 8  5  0  7+5 = 12 
# 9: 2 1  5  0  5 
# 10: 2 2  1  1  NA 
# 11: 2 3  2  0  1+2 = 3 
# 12: 2 4  2  1  NA 
# 13: 2 5  5  2  2 
# 14: 2 6  3  1  NA 
# 15: 2 7  5  1  3+5=8 
# 16: 2 8  4  1  5 

我希望得到使用data.table::shift功能這方面的工作,但我不確定如何讓使用多個滯後參數這項工作。

回答

6

試試這個:

dat[, TargetIndex:= .I + Shift] 

toMerge = dat[, list(Out = sum(Value)), by='TargetIndex'] 

dat[, TargetIndex:= .I] 

# dat = merge(dat, toMerge, by='TargetIndex', all=TRUE) 
dat[toMerge, on='TargetIndex', DesiredOutput:= i.Out] 

> dat 
#  ID Time Value Shift TargetIndex DesiredOutput 
# 1: 1 1  3  2   1   NA 
# 2: 1 2  3  2   2   NA 
# 3: 1 3  4  1   3    3 
# 4: 1 4  7  2   4    7 
# 5: 1 5  2  2   5   NA 
# 6: 1 6  7  0   6   14 
# 7: 1 7  7  1   7    2 
# 8: 1 8  5  0   8   12 
# 9: 2 1  5  0   9    5 
# 10: 2 2  1  1   10   NA 
# 11: 2 3  2  0   11    3 
# 12: 2 4  2  1   12   NA 
# 13: 2 5  5  2   13    2 
# 14: 2 6  3  1   14   NA 
# 15: 2 7  5  1   15    8 
# 16: 2 8  4  1   16    5 
+2

是啊,我張貼幾乎同樣的事情,但你的最後一步是做不必要的副本。你可以做'dat [toMerge,on =「TargetIndex」,DesiredOutput:= i.Out]'。 –

+2

我猜行索引可能比合並更便宜:'m = dat [,。(rid = Shift + .I,v = Value)] [rid <= .N,sum(v),by = rid]; dat [m $ rid,x:= m $ V1]'但我不確定這是否會給出預期的結果。另外,你可以動態地定義一個'by'列,比如'by =。(TargetIndex + Shift)',我想。 – Frank

+0

這太棒了。謝謝! –

相關問題