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

R语言分组去重:按ID&Group保留非零行的高效实现求助

问题:按ID+Group分组后保留非零行(仅处理有重复的分组)

示例数据集

ID    Group       Value    
   1     z1       0 
   1     z1       0.81 
   2     z2       2.89 
   2     z2       1.53
   3     z1       -0.23
   3     z1       0
   4     z3       10.75
   4     z3       8.13
   5     x2       0.45
   5     x2       1.43

对应的R数据构造代码:

library(tibble)
df <- tibble(
  ID = c(1, 1, 2, 2, 3, 3, 4, 4, 5, 5),
  Group = c("z1", "z1", "z2", "z2", "z1", "z1", "z3", "z3", "x2", "x2"),
  Value = c(0, 0.81, 2.89, 1.53, -0.23, 0, 10.75, 8.13, 0.45, 1.43)
)

需求说明

分组后若存在重复行(即每个ID+Group组内行数>1),仅保留Value列非零的行;无重复的分组则保留全部行。预期输出移除ID1和ID3中Value为0的行,其余分组保留所有行。

原代码问题分析

你提供的两段代码存在以下问题:

  • 分组列名错误:原数据列名为Group,代码中误写为GroupID
  • 效率低下:使用duplicated(.)会逐行比较整行内容,在22000行数据集上会大幅拖慢速度
  • 逻辑不准确:any(duplicated(.))仅判断分组内是否有整行重复,无法覆盖分组内多行非零的情况(如ID2、4、5的分组)

优化代码方案

方案1:dplyr高效写法

library(dplyr)

df %>%
  group_by(ID, Group) %>%
  # 分组行数为1则保留所有行,否则仅保留Value非零的行
  filter(n() == 1 | Value != 0) %>%
  ungroup()

方案2:data.table极速写法(适合大数据集)

如果数据集更大,推荐使用data.table,内存占用更低、运行速度更快:

library(data.table)

# 转换为data.table格式
setDT(df)
# 按ID+Group分组,逻辑同dplyr
df[, if (.N == 1) .SD else .SD[Value != 0], by = .(ID, Group)]

代码说明

  • n()(dplyr)或.N(data.table):直接统计分组内的行数,比duplicated(.)高效数倍,无需逐行比较
  • 逻辑简化:通过n() == 1判断是否为无重复分组,避免复杂的条件嵌套
  • 兼容性:覆盖所有分组场景,包括分组内全非零、含零值等情况

内容的提问来源于stack exchange,提问作者Ahir Bhairav Orai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:32:20