关于R语言dplyr的filter_at处理缺失值的技术问询
解决dplyr筛选含缺失值列与另一列组合条件的问题
首先我先帮你复现测试用的数据框(注意R里的缺失值一般用NA,和NaN在筛选逻辑上处理逻辑一致):
df <- data.frame( ID = 1:3, bank = c("own", "own", NA), type = c("online", "offline", "total"), stringsAsFactors = FALSE )
你的核心需求是筛选bank列为缺失值(NA/NaN)且type列为"total"的行,之前的filter_at写法问题出在逻辑方向和函数用法上:any_vars的作用是只要任意一个变量满足括号里的条件就保留行,但你需要的是两个条件同时成立,而且条件表达式也和需求不匹配。
最直观的正确写法
直接用filter函数把两个条件用&(逻辑与)连接,清晰易懂:
library(dplyr) l1 <- df %>% filter(is.na(bank) & type == "total") nrow(l1) # 输出1,完全符合你的预期
如果你想用dplyr推荐的across写法(替代旧的filter_at)
从dplyr 1.0.0版本开始,官方推荐用across替代filter_at这类scoped动词,如果你想尝试这种写法,可以这样写:
l1 <- df %>% filter( across(bank, is.na), across(type, ~ .x == "total") )
本质和上面的写法逻辑一致,只是用across来指定列对应的判断规则。
为什么你的原命令不对?
拆解一下你的原代码逻辑:
vec <- c("total") l1 <- df %>% filter_at(vars(type,bank), any_vars(!(. %in% vec) && (!is.na(.))))
这里的逻辑是:只要type或bank其中一个变量满足“不在vec里且不是缺失值”,就保留该行。
- 对于type列:
!(. %in% vec)会筛选出"online"和"offline"(它们不在vec里),同时!is.na(.)都满足,所以前两行的type符合条件; - 对于bank列:
!(. %in% vec)会包含"own"和NA(NA不在vec里),但!is.na(.)只保留"own",所以前两行的bank符合条件;
最终前两行都会被保留,nrow(l1)得到2,和你的预期不符。
内容的提问来源于stack exchange,提问作者Andi Maier
相关产品推荐
相关产品推荐

