R语言统计指定列含NA的行数并保留计数为0的分组方法
问题原因
- 你最初的写法用
filter_at提前把「Var2/Var3/Var4完全无NA」的行全筛掉了,后续分组计数时,像AL03这种所有行都被筛走的分组,自然不会出现在结果里。 any_vars()是旧版tidyverse作用域函数(*_at/*_all系列)专用的谓词函数,只能作为这类函数的内部参数使用,不能直接写在summarise的自定义计算逻辑里,所以会触发quosure类型的报错。
正确代码
当前tidyverse推荐用across()+if_any()替代旧的*_at+any_vars写法,不需要提前筛行,分组后直接逐行判断再求和即可,会自动保留计数为0的分组:
library(tidyverse) df %>% group_by(ID) %>% summarise( n = sum(if_any(c(Var2, Var3, Var4), is.na)) )
运行后输出结果完全匹配你的预期:
# A tibble: 3 × 2 ID n <chr> <int> 1 AL01 2 2 AL02 1 3 AL03 0
代码逻辑说明
if_any(c(Var2, Var3, Var4), is.na)逐行做判断:只要指定的三列里任意一列为NA,就返回TRUE,否则返回FALSE,完全覆盖之前any_vars(is.na(.))的判断逻辑。sum()直接对每个组内的逻辑结果计数:TRUE等价于1,FALSE等价于0,就算组内没有任何符合条件的行,求和结果也会是0,不会丢失分组。
如果你用的是1.0.0之前的旧版tidyverse,没有if_any函数,可以用兼容写法:
df %>% group_by(ID) %>% summarise( n = sum(rowSums(is.na(across(c(Var2, Var3, Var4)))) > 0) )
逻辑和上面完全一致:先提取选定列的NA状态,逐行统计NA个数,只要NA数大于0就判定为存在缺失,再分组求和。
内容的提问来源于stack exchange,提问作者lmar_nz
相关产品推荐
相关产品推荐

