R语言dplyr中组内存在元素满足条件时过滤整组的方法
问题说明
现有测试数据集如下:
df1 <- data.frame( id = c(1,1,2) , a = c('a','b','c')) df1 # id a # 1 1 a # 2 1 b # 3 2 c
需求为按id分组后,只要组内任意一行满足a == 'a'的条件,就删除该分组下的全部记录。
原有写法仅做了行级过滤,只删除了a == 'a'的单行,未删除id=1的全部分组记录:
df1 %>% group_by(id) %>% filter(a != 'a') # # A tibble: 2 × 2 # # Groups: id [2] # id a # <dbl> <chr> # 1 1 b # 2 2 c
错误原因
filter(a != 'a')是逐行判断的行级过滤逻辑:仅检查当前行的a列值是否不等于'a',不会对整个分组的全局特征做判断,因此id=1分组中a='b'的行因为本身满足a != 'a'被保留,达不到整组过滤的效果。
实现方案
dplyr 分组写法(推荐)
分组后对整个组做条件判断,仅保留完全不触发删除规则的分组即可,两种等价写法:
- 写法1:判断组内所有行都不满足删除条件
library(dplyr) df1 %>% group_by(id) %>% filter(all(a != 'a')) %>% ungroup()
- 写法2:判断组内不存在任何满足删除条件的行
df1 %>% group_by(id) %>% filter(!any(a == 'a')) %>% ungroup()
两种写法运行结果一致:
# A tibble: 1 × 2 id a <dbl> <chr> 1 2 c
提示:分组操作完成后建议加
ungroup()解除分组状态,避免后续数据处理意外受分组规则影响。
base R 原生写法
不加载第三方包也可以实现,逻辑为先找出所有需要删除的分组id,再做全表排除:
# 提取所有包含a='a'的id remove_id <- unique(df1$id[df1$a == 'a']) # 排除这些id对应的所有行 df1[!df1$id %in% remove_id, ]
内容的提问来源于stack exchange,提问作者marc
相关产品推荐
相关产品推荐

