在R中按指定列条件过滤行及获取被移除数据的技术问询
问题:基于特定前缀列的数据过滤与反向过滤实现
数据格式
| Genotype | Condition | Animal ID | D1 | D2 | PI3 |
|---|---|---|---|---|---|
| ctrl | vehicle | 1M123 | 0 | -18 | -30 |
| ko | treatment | 2M123 | 0 | -7 | -15 |
| ctrl | vehicle | 3M123 | 0 | -18 | -30 |
| ko | treatment | 4M123 | 0 | -7 | -15 |
需求说明
- 编写函数:过滤掉所有以
D或PI开头的列中值≤-20.5的行,同时保留含NA值的行(不同文件的这类列名称不同,但前缀固定为D或PI) - 现有正向过滤代码可运行,希望得到更优实现方式
- 编写反向过滤函数,返回被移除的行,但当前反向过滤代码无法正常执行
现有代码
正向过滤代码(可正常运行)
library(dplyr) filter.data<-function(mydata){ filtered<-mydata %>% filter( across( .cols=starts_with(c("D","PI")), .fns=any_vars(.>(-20.5)|is.na(.)) ) ) return(filtered) }
反向过滤代码(无法正常执行)
rm.data<-function(mydata){ filtered<-mydata %>% filter( across( .cols=starts_with(c("D","PI")), .fns=any_vars(.<(-20.5)& !is.na(.)) ) ) return(rm.data) }
解决方案
1. 正向过滤的优化实现
原代码逻辑没问题,但dplyr 1.0.0+推荐使用更现代的if_any替代any_vars,语法更清晰且兼容性更好:
library(dplyr) filter_data <- function(mydata) { mydata %>% filter( if_any(starts_with(c("D", "PI")), ~ .x > -20.5 | is.na(.x)) ) }
if_any的作用是:只要指定列中有任意一列满足值>-20.5或为NA,就保留该行,和原代码逻辑完全一致。
2. 反向过滤函数的修正
原反向过滤代码有两个致命问题:
- 返回语句错误:最后返回的是函数名
rm.data,而非处理后的结果filtered - 若需求是「保留任意一列值<-20.5且非NA的行」,修正后的代码如下:
rm_data <- function(mydata) { mydata %>% filter( if_any(starts_with(c("D", "PI")), ~ .x < -20.5 & !is.na(.x)) ) }
如果需求是「保留所有D/PI前缀列值都<-20.5且非NA的行」,则替换为if_all:
rm_data <- function(mydata) { mydata %>% filter( if_all(starts_with(c("D", "PI")), ~ .x < -20.5 & !is.na(.x)) ) }
内容的提问来源于stack exchange,提问作者Mushu Mushu
相关产品推荐
相关产品推荐

