如何使用summarize_all()统计数据集中各列的非NA值数量?
问题描述
我想要创建一个表格,统计数据集中每一列的非NA值数量。我正在使用summarize_all()函数,但无法得到正确的非NA值统计结果。
我参考了相关帖子获取思路,但似乎没能帮我得到想要的统计结果:如果传入summarize_all(n_distinct)会得到不同值的数量,而传入summarize_all(list(n=~n()))或summarize_all(list(n="length")),则会得到行数。
我的期望输出:
ID Female Male Non_Binary 5 5 4 3
我哪里出错了?
示例代码
# Sample Code test <- as_tibble(data.frame(`ID` = c("1","2","3","4","5"), `Female` = c("Female","Female","Female","Female","Female"), `Male` = c(NA,"Male","Male","Male","Male"), `Non_Binary`=c("Non-Binary","Non-Binary","Non-Binary",NA,NA))) ## Attempt 1 summary <- test %>% summarize_all(list(n=~n())) # 输出结果 # A tibble: 1 × 4 # ID_n Female_n Male_n Non_Binary_n # <int> <int> <int> <int> #1 5 5 5 5 ## Attempt 2 summary <- test %>% summarize_all(list(n="length")) # 输出结果 # A tibble: 1 × 4 # ID_n Female_n Male_n Non_Binary_n # <int> <int> <int> <int> #1 5 5 5 5 ## Attempt 3 summary <- test %>% summarize_all(n_distinct) # 输出结果 # A tibble: 1 × 4 # ID Female Male Non_Binary # <int> <int> <int> <int> #1 5 1 2 2 ### 期望输出 # ID Female Male Non_Binary # 5 5 4 3
解决方案
你之前的尝试没命中需求,核心问题是选的函数不对:
n()和length()返回的是列的总行数,不管单元格是不是NA;n_distinct()统计的是列里不同非NA值的个数,不是非NA值的总数量。
要统计每列的非NA值总数,这几种方法都能解决:
方法1:用summarize_all()结合sum(!is.na(.))
直接通过布尔值统计非NA的数量:
summary <- test %>% summarize_all(~sum(!is.na(.)))
运行后输出:
# A tibble: 1 × 4 ID Female Male Non_Binary <int> <int> <int> <int> 1 5 5 4 3
原理很简单:!is.na(.)把每个单元格转成TRUE(非NA)或FALSE(NA),sum()会自动把TRUE当成1、FALSE当成0,加起来就是非NA值的总数。
方法2:用naniar包的n_complete()(更直观)
如果你装了naniar包,直接用专门统计非NA值的函数,代码更简洁:
library(naniar) summary <- test %>% summarize_all(n_complete)
输出结果和方法1完全一致。
方法3:用across()替代已退役的summarize_all()
tidyverse现在推荐用across()代替旧的*_all()系列函数(summarize_all()已经被软弃用),写法如下:
summary <- test %>% summarize(across(everything(), ~sum(!is.na(.))))
或者结合naniar:
summary <- test %>% summarize(across(everything(), n_complete))
这样就能得到你想要的每列非NA值统计结果了。
内容的提问来源于stack exchange,提问作者Mary Rachel
相关产品推荐
相关产品推荐

