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

R中为连续同occ值分组新增首末nuc对应start/stop列的高效方法

问题描述

现有包含nuc、occ两个变量的数据框tel2,需要实现以下计算逻辑:

  • 新增start变量:识别所有连续相同occ值构成的独立序列,取每个序列第一行对应的nuc值,作为该序列所有行的start取值
  • 新增stop变量:针对上述连续相同occ值的独立序列,取每个序列最后一行对应的nuc值,作为该序列所有行的stop取值

注意:若同一occ值存在多段被其他值打断的不连续序列,需按独立分段分别计算,不可跨段合并。直接使用group_by(occ)分组无法识别非连续分段,不能满足需求。由于真实数据集规模达1000万行,需要优先选择运行效率足够高的实现方案。

测试数据构造代码

tel=data.frame(aa=c(153,113,163,117,193,162,110,109,186,103),
               bb=c(189,176,185,130,200,189,156,123,198,189),
               ID=c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J"))
nuc2=100:200
library(data.table)
tel2=as.data.frame(setDT(tel)[SJ(v=nuc2), on=.(aa<=v, bb>=v)][,.(occ = sum(!is.na(ID))), by=.(nuc=aa)])
最优实现方案(data.table,千万行级秒级完成)

核心逻辑是先为每段连续相同的occ生成唯一分组ID,再按分组取首尾nuc值即可。data.table底层为C实现,内存占用低、计算速度快,是千万行级数据的首选方案。

# 确保数据为data.table格式
setDT(tel2)

# 一行代码完成计算
tel2[, `:=`(start = first(nuc), stop = last(nuc)), by = .(grp = rleid(occ))]
  • 关键函数rleid(occ)是data.table内置的连续序列分组函数,每当occ值和上一行不同时就生成新的分组ID,天然解决相同值非连续的分段问题。
  • 计算完成后分组IDgrp不会实际写入数据框,无需额外删除字段。

结果验证

计算完成后取前29行查看结果:

> head(tel2, 29)
    nuc occ start stop
 1: 100   0   100  102
 2: 101   0   100  102
 3: 102   0   100  102
 4: 103   1   103  108
 5: 104   1   103  108
 6: 105   1   103  108
 7: 106   1   103  108
 8: 107   1   103  108
 9: 108   1   103  108
10: 109   2   109  109
11: 110   3   110  112
12: 111   3   110  112
13: 112   3   110  112
14: 113   4   113  116
15: 114   4   113  116
16: 115   4   113  116
17: 116   4   113  116
18: 117   5   117  123
19: 118   5   117  123
20: 119   5   117  123
21: 120   5   117  123
22: 121   5   117  123
23: 122   5   117  123
24: 123   5   117  123
25: 124   4   124  130
26: 125   4   124  130
27: 126   4   124  130
28: 127   4   124  130
29: 128   4   124  130

注:你给出的示例输出中14-17行start=103、25-29行stop=128属于笔误,按连续段逻辑,113-116为独立的occ=4段,首行nuc为113;124-130为occ=4段,尾行nuc为130。

备选方案(dplyr,不推荐千万行级使用)

如果习惯使用dplyr语法,可通过cumsum手动生成分组ID实现,但该方案速度比data.table慢3-5倍,内存占用更高,千万行数据运行时间较长:

library(dplyr)
tel2 <- tel2 %>%
  mutate(grp = cumsum(occ != lag(occ, default = first(occ)))) %>%
  group_by(grp) %>%
  mutate(start = first(nuc), stop = last(nuc)) %>%
  ungroup() %>%
  select(-grp)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:45:35