在另一列中按滞后值移动行值

Mik*_*han 4 performance r data.table

我有一个相当大的数据集,我有兴趣根据另一列的值向前推进"行进"值.例如,如果我有一个Value = 3at Time = 0和a 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)]
Run Code Online (Sandbox Code Playgroud)

假数据

#     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
Run Code Online (Sandbox Code Playgroud)

我希望每个人都Value按照Shift专栏向前推进.因此DesiredOutput,第3行的 列将等于3,因为at的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
Run Code Online (Sandbox Code Playgroud)

我希望使用该data.table::shift函数使这个工作,但我不确定如何使用多个滞后参数使这项工作.

sir*_*len 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
Run Code Online (Sandbox Code Playgroud)

  • 是的,我发布了几乎相同的东西,尽管你的最后一步是做不必要的复制.你可以做`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]`我不确定这会给出预期的结果.另外,fyi,你可以动态定义一个`by`列,比如`by =.(TargetIndex + Shift)`,我想. (2认同)