R语言使用dplyr单步实现按分组存在条件筛选所有行
问题
需要实现如下查询需求:
查询所有满足条件的个体:其所属的
homeworld(母星)、gender(性别)分组中,存在至少一个金发(hair_color取值为blond)蓝眼(eye_color取值为blue)的个体。
常规两步实现思路:
- 筛选所有同时满足金发、蓝眼条件的个体生成数据子集
- 提取子集中的
homeworld、gender取值,作为条件对原数据集二次过滤得到结果
现求基于dplyr语法的单步实现方案,原有两步法代码如下:
library(dplyr, warn.conflicts = FALSE) any_blond_blue <- starwars %>% group_by(homeworld, gender) %>% filter(eye_color == "blue", hair_color == "blond") starwars %>% filter( homeworld %in% any_blond_blue$homeworld, gender %in% any_blond_blue$gender ) #> # A tibble: 9 × 14 #> name height mass hair_color skin_color eye_color birth_year sex gender #> <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr> #> 1 Luke Sky… 172 77 blond fair blue 19 male mascu… #> 2 C-3PO 167 75 <NA> gold yellow 112 none mascu… #> 3 Darth Va… 202 136 none white yellow 41.9 male mascu… #> 4 Owen Lars 178 120 brown, gr… light blue 52 male mascu… #> 5 R5-D4 97 32 <NA> white, red red NA none mascu… #> 6 Biggs Da… 183 84 black light brown 24 male mascu… #> 7 Anakin S… 188 84 blond fair blue 41.9 male mascu… #> 8 Finis Va… 170 NA blond fair blue 91 male mascu… #> 9 Cliegg L… 183 NA brown fair blue 82 male mascu… #> # … with 5 more variables: homeworld <chr>, species <chr>, films <list>, #> # vehicles <list>, starships <list>
解答
直接用分组+any()判断即可单步完成,不需要创建中间对象,代码如下:
library(dplyr, warn.conflicts = FALSE) starwars %>% group_by(homeworld, gender) %>% filter(any(eye_color == "blue" & hair_color == "blond")) %>% ungroup()
运行结果和你给出的两步法输出完全一致,返回9条匹配记录。
几点说明:
any()会按分组做逻辑判断,只要组内存在至少一条记录满足金发蓝眼的条件,该组所有记录都会被保留,完全匹配需求- 末尾加
ungroup()是好习惯,避免后续数据操作意外受分组逻辑影响 - 你原来的两步法写法存在逻辑漏洞:分别用
%in%匹配homeworld和gender,可能误保留「homeworld在子集、gender也在子集,但二者的组合从未出现过金发蓝眼个体」的分组,分组判断的写法是严格按两个字段的组合校验,逻辑更严谨。
内容的提问来源于stack exchange,提问作者boshek
相关产品推荐
相关产品推荐

