【问题标题】:conditional rolling difference or gradient based on a column in data.table R基于data.table R中的列的条件滚动差异或梯度
【发布时间】:2021-08-19 08:40:05
【问题描述】:

我需要根据一个非常大的data.table中另一列的条件值来获取一列的梯度。

> require(data.table)
> DT = data.table( ID = c(rep('A', 8), rep('B', 6)),
                   Condition = c(0,1,0,0,1,1,0,1,0,0,1,0,0,1),
                   Value = c(4,3,2,1,4,3,2,1,4,3,2,1,4,3))

我想按 ID 获取“值”列的滚动梯度,仅适用于 Condition == 1 的行。

> desired_output
    ID Condition Value Gradient
 1:  A         0     4       NA    # condition isn't met so no gradient
 2:  A         1     3        0    # condition is met but there is no predecessor. Gradient set to 0
 3:  A         0     2       NA    # condition isn't met so no gradient
 4:  A         0     1       NA    # condition isn't met so no gradient
 5:  A         1     4        1    # condition is met and gradient is 4-3=1
 6:  A         1     3       -1    # condition is met and gradient is 3-4=-1
 7:  A         0     2       NA    # condition isn't met so no gradient
 8:  A         1     1       -2    # condition is met and gradient is 1-3=-2
 9:  B         0     4       NA
10:  B         0     3       NA
11:  B         1     2        0
12:  B         0     1       NA
13:  B         0     4       NA
14:  B         1     3        1

如果可能的话,我更喜欢原生 data.table 解决方案。

请注意:可以通过子设置 DT[Condition == 1] 然后重新加入结果来做到这一点。如果可能,我想避免子设置和重新加入。

【问题讨论】:

    标签: r data.table conditional-statements gradient


    【解决方案1】:
    library(data.table)
    library(magrittr)
    dt = data.table( ID = c(rep('A', 8), rep('B', 6)),
                     Condition = c(0,1,0,0,1,1,0,1,0,0,1,0,0,1),
                     Value = c(4,3,2,1,4,3,2,1,4,3,2,1,4,3))
    
    # 1
    dt[Condition == 1, Gradient := Value - shift(Value, fill = first(Value)), by = ID][]
    #>     ID Condition Value Gradient
    #>  1:  A         0     4       NA
    #>  2:  A         1     3        0
    #>  3:  A         0     2       NA
    #>  4:  A         0     1       NA
    #>  5:  A         1     4        1
    #>  6:  A         1     3       -1
    #>  7:  A         0     2       NA
    #>  8:  A         1     1       -2
    #>  9:  B         0     4       NA
    #> 10:  B         0     3       NA
    #> 11:  B         1     2        0
    #> 12:  B         0     1       NA
    #> 13:  B         0     4       NA
    #> 14:  B         1     3        1
    
    #2
    dt$grad <- c (NA, NA, -1, -2,1, -1, - 1, -2, NA, NA, NA, -1,2,1)
    
    dt[Condition == 1, Value2 := Value, by = ID] %>% 
      .[, Value2 := shift(nafill(Value2, "locf"))] %>% 
      .[ Value2 != 1, Gradient2 := Value - Value2] %>% 
      .[, Value2 := NULL] %>% 
      .[]
    #>     ID Condition Value Gradient grad Gradient2
    #>  1:  A         0     4       NA   NA        NA
    #>  2:  A         1     3        0   NA        NA
    #>  3:  A         0     2       NA   -1        -1
    #>  4:  A         0     1       NA   -2        -2
    #>  5:  A         1     4        1    1         1
    #>  6:  A         1     3       -1   -1        -1
    #>  7:  A         0     2       NA   -1        -1
    #>  8:  A         1     1       -2   -2        -2
    #>  9:  B         0     4       NA   NA        NA
    #> 10:  B         0     3       NA   NA        NA
    #> 11:  B         1     2        0   NA        NA
    #> 12:  B         0     1       NA   -1        -1
    #> 13:  B         0     4       NA    2         2
    #> 14:  B         1     3        1    1         1
    

    reprex package (v2.0.0) 于 2021-06-04 创建

    【讨论】:

    • 我没有意识到我可以使用 Condition == 1 作为过滤器,它会自动过滤掉其他所有内容以进行梯度计算。傻我。谢谢!
    • 很高兴能帮到你。我自己最近才知道这个“data.table”功能。
    • 我想我只需要先将每行 i (按 ID)的 last_row_with_condition=1 的值作为新列,然后进行正常减法。我看不出还有什么效率更高:)
    • 这里为什么需要管道? dt[Condition == 1, Value2 := Value, by = ID ][ ... ][ ... ][] 也可以。
    • 这样看代码更方便我
    猜你喜欢
    • 2021-08-28
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多