如何在dplyr中用向量指定列实现Lambda函数的OR条件过滤?
问题与解决方案
问题描述
给定如下数据集:
my_df <- data.frame(socks = c(1,1,0,1,0,0), hat = c(0,1,1,0,0,0), species = c('frog','pigeon','pigeon','cow','monkey','cow'), gender = c('M','F','M','F','M','M')) acc <- c('socks','hat')
需要过滤数据集,保留socks或hat任意一列等于1的观测(即第1-4行),且要求用向量acc指定列名,方便在函数中复用。
之前尝试的代码:
accessorized <- my_df %>% filter_at(vars(acc),all_vars(.==1)) accessorized <- my_df %>% filter(across(acc,~.x==1))
但这两段代码都只返回socks和hat同时等于1的观测(仅第2行),因为默认是**AND(且)条件,现在需要改成OR(或)**条件。
解决方法
方法1:使用if_any(dplyr 1.0.0+推荐写法)
if_any函数专门用来实现“任意一列满足条件”的逻辑,正好对应OR需求:
library(dplyr) accessorized <- my_df %>% filter(if_any(all_of(acc), ~ .x == 1))
all_of(acc)用来将字符向量转换为列引用,确保acc里的列名被正确识别if_any会检查每行中acc指定的列是否有任意一列等于1,满足则保留该行
方法2:用rowSums统计符合条件的列数
通过计算每行中acc列等于1的数量,只要数量大于0就保留:
accessorized <- my_df %>% filter(rowSums(select(., all_of(acc)) == 1) > 0)
select(., all_of(acc))选取acc指定的列==1生成布尔矩阵,rowSums计算每行中TRUE的数量(即等于1的列数)- 数量>0意味着至少有一列等于1,符合OR条件
方法3:旧版本dplyr用filter_at+any_vars
如果你用的是较旧版本的dplyr(1.0.0之前),可以把all_vars换成any_vars:
accessorized <- my_df %>% filter_at(vars(acc), any_vars(. == 1))
any_vars表示“任意一列满足条件”,替代之前的all_vars(所有列满足条件)
以上三种方法都能得到你需要的第1-4行观测结果。
内容的提问来源于stack exchange,提问作者Lothar the Quick
相关产品推荐
相关产品推荐

