如何用 data.table 有条件地用以前的值 "rowwisely" 填充列

How to conditionally fill column with previous values "rowwisely" with data.table

我的目标是有条件地用其他列上的先前值替换列中的值。这些值可以但不必丢失。我正在根据阈值检查变量 check,当 check 高于 th 时,我称其为匹配项。每当有匹配时,我想用它自己之前的观察替换 value唯一的问题是,当有顺序匹配时,我想将第一个值向前(向下)携带,而不是只用它自己的滞后替换。数据集几乎不符合我的记忆,所以最好使用 data.table

具体来说,假设我有以下数据

library(data.table)
library(dplyr)

dt <- data.table(tribble(
    ~id, ~check, ~value, 
    1,       .1,     10,
    2,       .6,     20,
    3,       .7,     50,
    4,       .5,     NA,
    5,       .1,     90,
    6,       .7,     NA,
))

并进行以下检查

th <- .5
dt[, ck_match := if_else(condition = check > th,
                         true = "matches_above",
                         false = "no_match")][]

#>    id check value      ck_match
#> 1:  1   0.1    10      no_match
#> 2:  2   0.6    20 matches_above
#> 3:  3   0.7    50 matches_above
#> 4:  4   0.5    NA      no_match
#> 5:  5   0.1    90      no_match
#> 6:  6   0.7    NA matches_above

这与我的目标很接近,但问题是在 row 3 中我的目标是 将值向前 id==1 直到第一个 no_match 而不是总是从 lag(value).

中获取值
dt[, ck_shift := if_else(condition = check > th,
                         true = shift(
                         false = value)][]
#>    id check value      ck_match ck_shift
#> 1:  1   0.1    10      no_match       10
#> 2:  2   0.6    20 matches_above       10
#> 3:  3   0.7    50 matches_above       20
#> 4:  4   0.5    NA      no_match       NA
#> 5:  5   0.1    90      no_match       90
#> 6:  6   0.7    NA matches_above       90

说的很清楚,我的目标是:

# id check value
# 1    0.1    10
# 2    0.6    10
# 3    0.7    10
# 4    0.5    NA
# 5    0.1    90
# 6    0.7    90

reprex package (v2.0.0)

于 2021-04-21 创建

我有一个解决方案。

  1. grprleid(ck_match)
  2. 生成的组ID
  3. last 是一个变量,存储前一组的最后一个值
library(data.table)
library(dplyr)

dt <- data.table(tribble(
    ~id, ~check, ~value, 
    1,       .1,     10,
    2,       .6,     20,
    3,       .7,     50,
    4,       .5,     NA,
    5,       .1,     90,
    6,       .7,     NA,
))
th <- .5
dt[, ck_match := fifelse(check > th,
                         "matches_above",
                         "no_match")]
dt[, grp := rleid(ck_match)]
this <- NA_real_
dt[, value := {last <- this; this <- last(value); last; fifelse(check <= th, value, last)},
   by = grp]
dt[,`:=`(ck_match = NULL, grp = NULL)][]
#>    id check value
#> 1:  1   0.1    10
#> 2:  2   0.6    10
#> 3:  3   0.7    10
#> 4:  4   0.5    NA
#> 5:  5   0.1    90
#> 6:  6   0.7    90

reprex package (v2.0.0)

于 2021-04-22 创建