我在过去两周内遇到过这个问题两次,所以我认为值得发帖.我正在尝试识别内部的"运行" data.table,但我无法找到一种优雅的方法来实现它.
set.seed(2016)
dt <- data.table(ID = 1:50, Char = sample(LETTERS, 50, replace=TRUE))
dt <- dt[order(Char, ID)]
ID Char
1: 9 A
2: 10 B
3: 20 C
4: 42 C
5: 2 D
6: 4 D
7: 6 D
8: 18 D
...
Run Code Online (Sandbox Code Playgroud)
在这里,我想识别和分组ID在上/下行的2行内的行.这是我目前难看的解决方案
# Runs of 2 or more IDs within 2 of each other
dt[, `:=`(InRun = FALSE, InRunStart = FALSE)]
dt[abs(ID - shift(ID, type="lag")) <= 2 | abs(shift(ID, type="lead") - ID) <= 2, InRun := TRUE]
dt[InRun == TRUE & abs(ID - shift(ID, type="lag")) > 2 | is.na(shift(ID, type="lag")), InRunStart := TRUE]
dt[InRun == TRUE, RunID := cumsum(InRunStart)]
dt[, c("InRun", "InRunStart") := NULL]
dt
ID Char RunID
1: 9 A 1
2: 10 B 1
3: 20 C NA
4: 42 C NA
5: 2 D 2
6: 4 D 2
7: 6 D 2
8: 18 D NA
...
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
编辑:似乎对我如何定义"运行"存在一些困惑.更明确地说,当且仅当它们的ID在2的距离内时,row_i和row_i + 1应该具有相同的RunID.
生成此运行 ID 后我会停止:
dt[, run_id0 := 1L + cumsum(abs(ID - shift(ID, fill=ID[1L])) > 2)]
Run Code Online (Sandbox Code Playgroud)
但要获取 OP 的运行 ID(忽略长度为 1 的运行),可以采用以下几种方法:
dt[duplicated(run_id0) | duplicated(run_id0, fromLast=TRUE), run_id1 := .GRP, by=run_id0 ]
# or
dt[, run_len := .N, by=run_id0 ][ run_len > 1L, run_id2 := .GRP, by=run_id0 ]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |