r - 在条件之前和之后的行中添加包含数据的列
问题描述
受这篇文章的启发,我想出了一个解决方案,在 y==5 之前和之后添加一个 1 的 2 行的列。像这样:
library(data.table)
DT <- fread("grp y exclude
a 1 0
a 2 0
a 3 0
a 4 1
a 5 0
a 7 1
a 8 0
a 9 0
a 10 0
b 1 0
b 2 0
b 3 0
b 4 1
b 5 0
b 6 1
b 7 1
b 8 0
b 9 0
b 10 0
c 5 1
d 1 0")
DT[DT[, rn := .I][, rn[abs(.I - .I[y==5]) <= 2], by=grp]$V1, xx:=1]
我的问题是,如果条件太接近顶部,它会抛出警告并且无法正常工作:
DT$y[2] <- 5
DT[DT[, rn := .I][, rn[abs(.I - .I[y==5]) <= 2], by=grp]$V1, xx:=1]
Warning message:
In .I - .I[y == 5] :
longer object length is not a multiple of shorter object length
我怀疑该索引会给出小于 1 的数字,但无法弄清楚。有什么建议可以更改代码以使其在所有条件下都能正常工作吗?
想要的输出:
grp y exclude xx
1: a 1 0 1
2: a 5 0 1
3: a 3 0 1
4: a 4 1 1
5: a 5 0 1
6: a 7 1 1
7: a 8 0 1
8: a 9 0 0
9: a 10 0 0
10: b 1 0 0
11: b 2 0 0
12: b 3 0 1
13: b 4 1 1
14: b 5 0 1
15: b 6 1 1
16: b 7 1 1
17: b 8 0 0
18: b 9 0 0
19: b 10 0 0
20: c 5 1 1
21: d 1 0 0
解决方案
这是另一种使用shift
val <- 5L
DT[, xx := as.integer(
Reduce(`|`, c(shift(y==val, 0L:2L, fill=FALSE), shift(y==val, 1L:2L, FALSE, "lead")))
),
by=.(grp)]
DT
结合 Jaap 的评论,使用 data.table 版本 >= 1.12.0,代码缩短为
DT[, xx := +(Reduce(`|`, shift(y==v, -2L:2L, FALSE))), by=grp]
输出:
grp y exclude xx
1: a 1 0 1
2: a 5 0 1
3: a 3 0 1
4: a 4 1 1
5: a 5 0 1
6: a 7 1 1
7: a 8 0 1
8: a 9 0 0
9: a 10 0 0
10: b 1 0 0
11: b 2 0 0
12: b 3 0 1
13: b 4 1 1
14: b 5 0 1
15: b 6 1 1
16: b 7 1 1
17: b 8 0 0
18: b 9 0 0
19: b 10 0 0
20: c 5 1 1
21: d 1 0 0
grp y exclude xx
推荐阅读
- powershell - Powershell 错误变量抛出“变量未分配”异常
- node.js - 用postgres在sequelize中通过嵌套对象值查找
- typescript - 如何告诉 TypeScript 允许列表中的多个字符串,每个字符串在展开参数中只允许一次?
- postgresql - 错误:未为索引 document_bt_id_sys_period_app_period_excl 定义函数 ammarkpos
- android - Android动画旋转属性不起作用
- python - 如何使图表更清晰
- javafx - 按键抽搐时的 KeyEvent
- c - 如何在 STM32F103C8T6 上使裸机 LED 闪烁?
- javascript - 调用函数时,预期 spy toggleStyle 已被调用
- kubernetes - Prometheus / Kubernetes 显示 InstanceDown / PrometheusTargetMissing