如何用 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 创建
我有一个解决方案。
grp
是rleid(ck_match
) 生成的组ID
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 创建
我的目标是有条件地用其他列上的先前值替换列中的值。这些值可以但不必丢失。我正在根据阈值检查变量 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 创建我有一个解决方案。
grp
是rleid(ck_match
) 生成的组ID
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 创建