2016-12-12 33 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

这太棒了。谢谢! –

相关问题