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

如何用data.table按ID统计break_flag标记行的上下行数

需求实现方案

按id分组,将每个break_flag=1的标记行与其前后连续的非标记行(直到下一个标记行或组边界)划分为一个区块,统计每个区块的总行数(标记行自身计1行),并将该数值赋值给区块内所有行。

步骤1:加载并初始化数据

library(data.table)
x <- data.table(id = c(rep("123", 6), rep("234", 4)),
                value = c(1,6,5,10,3,2, 4,6,10,5))
x[, break_flag := ifelse(value == 10, 1, 0)]

步骤2:生成区块并统计行数

# 按id分组,生成基于break_flag的连续分组ID
x[, r := rleid(break_flag), by = id]

# 按id分组,确定包含标记行的分组ID
x[, break_r := unique(r[break_flag == 1]), by = id]

# 构建区块映射:将标记行分组及其前后非标记行分组合并为同一区块
x[, block := {
  r_vals <- unique(r)
  break_rs <- break_r
  block_map <- integer(length(r_vals))
  
  for (br in break_rs) {
    idx <- which(r_vals == br)
    block_map[idx] <- br
    # 合并前一个非标记行分组(如果存在)
    if (idx > 1 && break_flag[r_vals[idx-1] == r][1] == 0) {
      block_map[idx-1] <- br
    }
    # 合并后一个非标记行分组(如果存在)
    if (idx < length(r_vals) && break_flag[r_vals[idx+1] == r][1] == 0) {
      block_map[idx+1] <- br
    }
  }
  
  # 处理无标记行的分组(当前数据无此情况,可选保留)
  if (length(break_rs) == 0) block_map <- rep(1, length(r_vals))
  
  block_map[match(r, r_vals)]
}, by = id]

# 按id和block分组,计算每个区块的总行数
x[, line_count := .N, by = .(id, block)]

最终结果

运行后x的输出如下:

id value break_flag r break_r block line_count
 1: 123     1          0 1       2     2          6
 2: 123     6          0 1       2     2          6
 3: 123     5          0 1       2     2          6
 4: 123    10          1 2       2     2          6
 5: 123     3          0 3       2     2          6
 6: 123     2          0 3       2     2          6
 7: 234     4          0 1       2     2          4
 8: 234     6          0 1       2     2          4
 9: 234    10          1 2       2     2          4
10: 234     5          0 3       2     2          4

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:10:23