You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不使用split()的情况下按id与连续category分组data.table

问题:无需拆分id的data.table连续批次标识生成方法

需求说明

现有data.table格式数据,id与category为分组变量,数据已按指定顺序排列。需要在每个id组内,为category的连续出现批次生成group标识:同一id下,同一category的非连续连续段需标记不同的group值,同一连续段内标记相同值。例如id=1中B100有两次连续出现(第1-2行、第5行),需分别标记为1和2。

当前实现使用两次data.table::rleid(),但第二步需要按id拆分数据,现寻求无需拆分id的实现方法。

原始数据示例

id category
 1:  1     B100
 2:  1     B100
 3:  1     D300
 4:  1     D300
 5:  1     B100
 6:  2     B100
 7:  2     F500
 8:  2     F500
 9:  2     E600
10:  2     E600
11:  3     T400
12:  3     B100
13:  3     T400
14:  3     T400

期望输出

id category group
 1:  1     B100     1 # 第1次连续出现B100(id=1),长度2
 2:  1     B100     1
 3:  1     D300     1
 4:  1     D300     1
 5:  1     B100     2 # 第2次连续出现B100(id=1),长度1
 6:  2     B100     1
 7:  2     F500     1
 8:  2     F500     1
 9:  2     E600     1
10:  2     E600     1 # id=2无重复连续category,故均为1
11:  3     T400     1
12:  3     B100     1
13:  3     T400     2 # 第2次连续出现T400(id=3),长度2
14:  3     T400     2

当前实现(需拆分id)

library(data.table)

DT[, group := rleid(category), by = id]

DT <- split(DT, by = "id")

DT <- lapply(DT,
       \(x) x[, group := rleid(group), by = category])

DT <- rbindlist(DT)

无需拆分id的解决方案

直接利用data.table的分组嵌套操作,无需拆分数据,两步即可完成:

方法代码

library(data.table)
setDT(DT)

# 第一步:为每个id内的连续category段生成临时标识
DT[, temp_rleid := rleid(category), by = id]
# 第二步:针对每个id+category组合,对临时标识生成批次序号
DT[, group := rleid(temp_rleid), by = .(id, category)]
# 清理临时列(可选)
DT[, temp_rleid := NULL]

简洁链式写法

也可以合并为一行链式操作,省去临时列:

setDT(DT)[, group := rleid(rleid(category)), by = .(id, category)]

原理说明

  1. 内层rleid(category), by = id:为每个id内的连续category段生成唯一标识,比如id=1中两次B100连续段会得到不同的标识值。
  2. 外层rleid(...) , by = .(id, category):针对每个id+category组合,对上述连续段标识再次生成rleid,即可得到该category在对应id内的连续批次序号。

可复制测试数据

DT <- data.frame(id = c(rep(1,5), rep(2,5), rep(3,4)),
           category = c("B100","B100","D300","D300","B100",
                        "B100","F500","F500","E600","E600",
                        "T400","B100","T400","T400"))

# 期望结果对照
Output <- data.frame(id = c(rep(1,5), rep(2,5), rep(3,4)),
           category = c("B100","B100","D300","D300","B100",
                        "B100","F500","F500","E600","E600",
                        "T400","B100","T400","T400"),
           group = c(1,1,1,1,2,1,1,1,1,1,1,1,2,2))

内容的提问来源于stack exchange,提问作者diomedesdata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:45:41