在R的data.table中标记连续0值的分组并编号
问题描述
现有如下data.table数据集:
set.seed(0) data <- data.table(id = as.factor(c(rep("C001", 3), "C002", rep("C003", 5), rep("C004", 2), rep("C005", 7))), period = as.factor(c(1, 2, 3, 2, 1, 4, 5, 6, 10, 3, 4, 2, 3, 4, 7, 8, 9, 10)), industry = as.factor(c(rep("Finance", 3), "Culture", rep("Nutrition", 5), rep("Finance", 2), rep("Medicine", 7))), present = rbinom(18, 1, prob = 0.3))
需要新增一列present_count,对连续的present=0分组进行编号标记:
- 当
present=1时,标记为"1" - 当
present=0时,按连续组依次标记为"0_1"、"0_2"、"0_3"...
预期输出示例:
set.seed(0) data.table(id = as.factor(c(rep("C001", 3), "C002", rep("C003", 5), rep("C004", 2), rep("C005", 7))), period = as.factor(c(1, 2, 3, 2, 1, 4, 5, 6, 10, 3, 4, 2, 3, 4, 7, 8, 9, 10)), industry = as.factor(c(rep("Finance", 3), "Culture", rep("Nutrition", 5), rep("Finance", 2), rep("Medicine", 7))), present = rbinom(18, 1, prob = 0.3), present_count = c("1", "0_1", "0_1", "0_1", "1", "0_2", "1", "1", "0_3","0_3","0_3","0_3","0_3","0_3","0_3","1","0_4", "1"))
已知用while循环可实现,但数据集规模大时效率低下,需高效实现方法。
高效解决方案
利用data.table内置的rleid()函数(快速生成连续分组ID),结合分组赋值实现矢量化操作,避免循环,大幅提升效率:
set.seed(0) data <- data.table(id = as.factor(c(rep("C001", 3), "C002", rep("C003", 5), rep("C004", 2), rep("C005", 7))), period = as.factor(c(1, 2, 3, 2, 1, 4, 5, 6, 10, 3, 4, 2, 3, 4, 7, 8, 9, 10)), industry = as.factor(c(rep("Finance", 3), "Culture", rep("Nutrition", 5), rep("Finance", 2), rep("Medicine", 7))), present = rbinom(18, 1, prob = 0.3)) # 生成连续分组ID,以present的变化为分界 data[, rleid := rleid(present)] # 为present=0的组分配全局递增编号 data[present == 0, group_num := .GRP, by = rleid] # 生成目标列present_count data[, present_count := ifelse(present == 1, "1", paste0("0_", group_num))] # 可选:删除中间辅助列 data[, c("rleid", "group_num") := NULL]
核心逻辑说明:
rleid(present)会为每一段连续相同的present值生成唯一ID,确保同一连续0组被分到同一ID下- 对
present=0的组按rleid分组,.GRP会自动生成全局递增的组编号 - 全程为矢量化操作,无需遍历行,处理百万级以上数据时效率远高于循环方法
内容的提问来源于stack exchange,提问作者reinoud
相关产品推荐
相关产品推荐

