R语言按id、name分组移除class为0行筛选数据子集的方法
R语言按分组条件移除行高效实现
需求规则
- 针对data.frame类型数据集,以
id、name两个字段为分组维度 - 若某分组内存在多条记录,移除该分组内
class字段取值为0的行 - 若某分组仅1条记录,无论
class取何值都完整保留 - 方案需适配数千条及以上规模数据,保证处理效率
测试数据
Data <- data.frame(id = c(1,1,2,2,3,4,5), name = c("asd","asd","pqr","pqr","fgh","yut","kju"), date = c("02/03/2022","10/05/2022","23/01/2022","15/04/2022","19/05/2022","14/02/2022","10/06/2022"), class = c(0,1,0,1,0,0,1))
实现方案
方案1:data.table实现(性能最优,推荐大数据量场景使用)
data.table的分组处理性能极高,万级以内数据基本毫秒级完成,适合数据量较大的场景:
library(data.table) # 转换为data.table对象(直接修改原对象,无额外拷贝) setDT(Data) # 按规则过滤 result <- Data[, if(.N > 1) .SD[class != 0] else .SD, by = .(id, name)] # 如需转回普通data.frame格式,执行下一句即可 # setDF(result)
代码逻辑说明:
.N为data.table分组语法,代表当前分组的总行数- 分组行数大于1时,返回组内
class不等于0的行;分组行数为1时返回组内全部行
方案2:dplyr实现(tidyverse生态,可读性强)
如果日常使用tidyverse系列工具较多,可直接使用dplyr的分组过滤逻辑,性能完全满足数千条数据的处理需求:
library(dplyr) result <- Data %>% group_by(id, name) %>% filter(if(n() > 1) class != 0 else TRUE) %>% ungroup()
处理结果验证
两种方案返回的结果完全一致,符合预期:
| id | name | date | class |
|---|---|---|---|
| 1 | asd | 10/05/2022 | 1 |
| 2 | pqr | 15/04/2022 | 1 |
| 3 | fgh | 19/05/2022 | 0 |
| 4 | yut | 14/02/2022 | 0 |
| 5 | kju | 10/06/2022 | 1 |
补充说明:如果同
id+name的分组内存在多条class非0的记录,上述代码会全部保留;如果需要每个分组仅保留1条非0记录,可在过滤逻辑后增加切片/去重步骤。
内容的提问来源于stack exchange,提问作者joy_1379
相关产品推荐
相关产品推荐

