R语言如何按列位置而非列名对数据集进行dplyr多条件筛选
R语言按列位置筛选数据集的实现方法
原有写法错误原因
你第一种写法中filter(retag, c(4:50) != 8 & c(90:110) == 8)是直接对450、90110的整数序列做判断,和数据集列完全无关,自然无法得到正确结果。第二种rowSums的思路是可行的,只需要补充多条件的逻辑组合即可。
实现方案
方法1:dplyr方案(常规场景推荐)
使用dplyr 1.0.0及以上版本支持的if_all/if_any函数,cols参数直接传入列位置向量即可实现按位置筛选:
if_all:匹配指定列全部满足条件的行if_any:匹配指定列至少有一列满足条件的行
示例代码(匹配需求:第450列所有值不等于8,且第90110列所有值等于8):
library(dplyr) y <- retag %>% filter( if_all(cols = 4:50, ~.x != 8), if_all(cols = 90:110, ~.x == 8) )
如果需要改为“第450列至少有一个值不等于8,且第90110列至少有一个值等于8”,把if_all替换为if_any即可。
方法2:base R rowSums方案
通过多条件组合扩展你原有rowSums的写法即可实现需求:
全部列满足条件的场景
# 条件1:4~50列所有值都不等于8(等于8的列数为0) cond1 <- rowSums(retag[,4:50] == 8) == 0 # 条件2:90~110列所有值都等于8(不等于8的列数为0) cond2 <- rowSums(retag[,90:110] != 8) == 0 y <- retag[cond1 & cond2, ]
至少一列满足条件的场景
# 条件1:4~50列至少有1个值不等于8 cond1 <- rowSums(retag[,4:50] != 8) >= 1 # 条件2:90~110列至少有1个值等于8 cond2 <- rowSums(retag[,90:110] == 8) >= 1 y <- retag[cond1 & cond2, ]
方法3:超大数据集优化方案
如果数据集行数超过100万,推荐用data.table包实现,运算效率远高于dplyr和base R:
library(data.table) # 转换为data.table格式 setDT(retag) # 对应全部列满足条件的筛选逻辑 y <- retag[rowSums(.SD[,4:50] == 8) == 0 & rowSums(.SD[,90:110] != 8) == 0]
内容的提问来源于stack exchange,提问作者fhaney
相关产品推荐
相关产品推荐

