如何在R data.table中为某列连续相同值分组分配递增索引
问题描述
我有如下data.table:
example <- data.table(time = 1:30, A = c(rep("a", 5), rep("b", 5), rep("a", 5), rep("b", 2), rep("a", 8), rep("b", 3), rep("a", 2)))
需要基于A列分配递增索引,得到如下输出:
time A B 1 a 1 2 a 1 3 a 1 4 a 1 5 a 1 6 b 1 7 b 1 8 b 1 9 b 1 10 b 1 11 a 2 12 a 2 13 a 2 14 a 2 15 a 2 16 b 2 17 b 2 18 a 3 19 a 3 20 a 3 21 a 3 22 a 3 23 a 3 24 a 3 25 a 3 26 b 3 27 b 3 28 b 3 29 a 4 30 a 4
希望得到data.table方案或其他可行解决办法。
解决方案
data.table 实现方案
通过检测A列的切换点(从非a切换到a),对切换点做累积和即可生成目标索引列B:
library(data.table) example <- data.table(time = 1:30, A = c(rep("a", 5), rep("b", 5), rep("a", 5), rep("b", 2), rep("a", 8), rep("b", 3), rep("a", 2))) # 生成索引列B example[, B := cumsum(c(TRUE, A[-1] != A[-length(A)] & A[-1] == "a"))]
逻辑说明
A[-1] != A[-length(A)]:判断当前行与前一行的A值是否不同& A[-1] == "a":仅筛选从非a切换到a的情况c(TRUE, ...):第一行默认属于第一个索引块,开头补TRUEcumsum():对切换标记做累积和,得到递增的索引值
验证结果
运行代码后,example的输出与需求完全一致:
> example time A B 1: 1 a 1 2: 2 a 1 3: 3 a 1 4: 4 a 1 5: 5 a 1 6: 6 b 1 7: 7 b 1 8: 8 b 1 9: 9 b 1 10: 10 b 1 11: 11 a 2 12: 12 a 2 13: 13 a 2 14: 14 a 2 15: 15 a 2 16: 16 b 2 17: 17 b 2 18: 18 a 3 19: 19 a 3 20: 20 a 3 21: 21 a 3 22: 22 a 3 23: 23 a 3 24: 24 a 3 25: 25 a 3 26: 26 b 3 27: 27 b 3 28: 28 b 3 29: 29 a 4 30: 30 a 4
其他可行方案(dplyr)
若习惯使用dplyr,可通过以下代码实现:
library(dplyr) example %>% mutate( switch_flag = case_when( row_number() == 1 ~ TRUE, A != lag(A) & A == "a" ~ TRUE, TRUE ~ FALSE ), B = cumsum(switch_flag) ) %>% select(-switch_flag)
内容的提问来源于stack exchange,提问作者s.cerioli
相关产品推荐
相关产品推荐

