summarytools中freq()排除NA后转data.frame异常的解决方法咨询
解决summarytools::freq()设置report.nas=FALSE后转data.frame仍包含缺失值的问题
问题说明
使用summarytools包的freq()函数时,设置report.nas = FALSE可以在打印时排除缺失值,但将结果转为data.frame后,缺失值行被重新包含,总观测数仍为原始样本量(而非排除NA后的数量)。
复现代码
# 创建包含缺失值的smoker向量 smoker <- c("yes", "no", "yes", NA, NA, NA, "yes", "no", "yes", "no") df <- data.frame(smoker) library(summarytools) library(dplyr) # 生成排除缺失值的频率表(打印时正确) freq(df$smoker, report.nas = FALSE) # 转为data.frame后出现问题 table <- as.data.frame(freq(df$smoker, report.nas = FALSE)) # 或用dplyr管道 table <- df %>% freq(smoker, report.nas = FALSE) %>% as.data.frame() table
预期与实际结果差异
- 预期:仅保留有效观测(n=7),无缺失值行
- 实际:缺失值行
<NA>被保留,总观测数为原始的10
原因分析
freq()函数生成的对象内部存储了完整的统计数据(包括缺失值相关的统计),report.nas = FALSE仅控制打印输出时隐藏缺失值行,而as.data.frame.freq方法默认会提取所有统计字段,因此转成data.frame后会恢复缺失值行和原始总样本量。
解决方案
方法1:使用getSummary()提取显示用表格
freq对象的summary属性就是report.nas = FALSE时显示的内容,直接用getSummary()提取即可得到符合预期的data.frame:
freq_obj <- freq(df$smoker, report.nas = FALSE) table <- getSummary(freq_obj) table
输出结果:
Freq % % Cum. no 3 42.86 42.86 yes 4 57.14 100.00 Total 7 100.00 100.00
方法2:手动过滤已生成的data.frame
如果已经得到包含缺失值的data.frame,可手动筛选行并修正Total统计:
table <- as.data.frame(freq(df$smoker, report.nas = FALSE)) filtered_table <- table %>% # 移除缺失值行和原始Total行 filter(!rownames(.) %in% c("<NA>", "Total")) %>% # 添加修正后的Total行 bind_rows( data.frame( Freq = sum(.$Freq), `% Valid` = 100, `% Valid Cum.` = 100, `% Total` = 100, `% Total Cum.` = 100, row.names = "Total" ) ) filtered_table
循环生成频率表并应用kable样式
针对多变量循环处理,并结合knitr::kable生成格式化表格:
library(knitr) # 扩展数据框,添加另一个分类变量 df$drinker <- c("yes", "no", NA, "yes", "no", "yes", "no", NA, "yes", "no") # 循环处理每个分类变量 for (var in c("smoker", "drinker")) { freq_obj <- freq(df[[var]], report.nas = FALSE) result_table <- getSummary(freq_obj) # 输出带标题的kable表格 cat(paste0("\n### ", var, " 频率表(排除缺失值)\n")) print(kable(result_table, align = "c", caption = paste(var, "有效观测频率统计"))) }
内容的提问来源于stack exchange,提问作者Kristine
相关产品推荐
相关产品推荐

