如何使用 dplyr 或 data.table 按数据子集组执行前瞻计算?

How to use dplyr or data.table to perform look-ahead calculations by groups of data subsets?

我有兴趣使用 dplyr(为了方便)and/or data.table(为了速度,因为要操作的实际数据有 300 万多行)执行“前瞻”计算一个数据集,按分组的子集,然后标记那些前瞻性计算 return 值为 0 的行。底部的图像更好地说明了我正在尝试做的事情,其中​​ State_1 是添加到原始 data 数据帧的列(例如通过 dplyr mutate(...))。有关如何执行此操作的任何建议?

掌握前瞻性计算会有很大帮助,这是我在 XLS 中一直笨拙地处理的事情。

data 数据框开始,紧接着生成代码:

> data
   ID Period Values_1 Values_2 State
1   1      1        5        5    X0
2   1      2        0        2    X1
3   1      3        0        0    X2
4   1      4        0       12    X1
5   2      1        1        2    X0
6   2      2        0        0    X2
7   2      3        0        0    X0
8   2      4        0        0    X0
9   3      1        0        0    X2
10  3      2        0        0    X1
11  3      3        0        0    X9
12  3      4        0        2    X3
13  4      1        1        4    X2
14  4      2        2        5    X1
15  4      3        3        6    X9
16  4      4        0        0    X3

data <- 
  data.frame(
    ID = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4),
    Period = c(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4),
    Values_1 = c(5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0),
    Values_2 = c(5, 2, 0, 12, 2, 0, 0, 0, 0, 0, 0, 2, 4, 5, 6, 0),
    State = c("X0","X1","X2","X1","X0","X2","X0","X0", "X2","X1","X9","X3", "X2","X1","X9","X3")
  )

这是我要完成的工作的示例:

我们可以使用分组方法 - 按 'ID' 分组,在 'Values' 列上循环 if_all 到 return TRUE 对于只有 0 个值的行,然后创建一个索引,其中 last 位置不是最后一次观察以及创建的索引和 replace

library(dplyr)
data %>%
   group_by(ID) %>%
   mutate(ind1 =  if_all(starts_with('Values'), ~ .x == 0), 
       ind2 = last(which(ind1))== n() & ind1, 
     State_1 = replace(State, ind2, 'XX'), ind1 = NULL, ind2 = NULL) %>%
   ungroup

-输出

# A tibble: 16 × 6
      ID Period Values_1 Values_2 State State_1
   <dbl>  <dbl>    <dbl>    <dbl> <chr> <chr>  
 1     1      1        5        5 X0    X0     
 2     1      2        0        2 X1    X1     
 3     1      3        0        0 X2    X2     
 4     1      4        0       12 X1    X1     
 5     2      1        1        2 X0    X0     
 6     2      2        0        0 X2    XX     
 7     2      3        0        0 X0    XX     
 8     2      4        0        0 X0    XX     
 9     3      1        0        0 X2    X2     
10     3      2        0        0 X1    X1     
11     3      3        0        0 X9    X9     
12     3      4        0        2 X3    X3     
13     4      1        1        4 X2    X2     
14     4      2        2        5 X1    X1     
15     4      3        3        6 X9    X9     
16     4      4        0        0 X3    XX   

一个data.table解决方案。与其向前看,不如向后看。

setDT(data)[, State1 := ifelse(rev(cumsum(rev(Values_1 + Values_2))), State, "XX"), ID]
data
#>     ID Period Values_1 Values_2 State State1
#>  1:  1      1        5        5    X0     X0
#>  2:  1      2        0        2    X1     X1
#>  3:  1      3        0        0    X2     X2
#>  4:  1      4        0       12    X1     X1
#>  5:  2      1        1        2    X0     X0
#>  6:  2      2        0        0    X2     XX
#>  7:  2      3        0        0    X0     XX
#>  8:  2      4        0        0    X0     XX
#>  9:  3      1        0        0    X2     X2
#> 10:  3      2        0        0    X1     X1
#> 11:  3      3        0        0    X9     X9
#> 12:  3      4        0        2    X3     X3
#> 13:  4      1        1        4    X2     X2
#> 14:  4      2        2        5    X1     X1
#> 15:  4      3        3        6    X9     X9
#> 16:  4      4        0        0    X3     XX