如何在gtsummary中新增「不适用」分类并排除其占比分母计算
gtsummary 区分缺失值与「不适用」案例的实现方法
核心思路是通过自定义分类变量统计逻辑,直接在tbl_summary()内部完成有效样本占比计算、两类非有效样本的单独计数,不需要拆分表格堆叠,也不会把非有效样本计入占比分母。
具体实现步骤:
- 数据预处理阶段就拆分两类非有效回答:把符合「不适用」逻辑的样本(比如本例中的男性受访者怀孕状态)单独编码为统一的文本标签
"不适用",真正未作答的缺失值保留为原生NA即可,不要把两类值都填成NA。 - 编写适配gtsummary的自定义统计函数,核心规则:
- 计算分类占比时,分母仅纳入既不是NA、也不等于
"不适用"的有效回答样本 - 单独统计「不适用」和缺失值的样本量,作为独立行展示
- 计算分类占比时,分母仅纳入既不是NA、也不等于
- 调用
tbl_summary()时关闭默认的缺失值自动统计,传入自定义统计函数即可。
可直接运行的示例代码:
library(tidyverse) library(gtsummary) # 预处理示例数据:拆分不适用和真正的缺失值 tab <- tibble( sex = c(rep("M", 10), rep("F", 10)), pregnant = c(rep("不适用", 10), rep(NA, 2), rep("0", 6), rep("1", 2)) ) |> mutate(pregnant = factor(pregnant, levels = c("0", "1", "不适用"))) # 自定义分类变量统计函数 cat_stat_custom <- function(data, variable, ...) { var_col <- data[[variable]] # 筛选有效回答样本 valid_mask <- !is.na(var_col) & var_col != "不适用" valid_total <- sum(valid_mask) # 计算有效分类的n和占比 valid_count <- table(var_col[valid_mask]) valid_stat <- map_chr(valid_count, ~glue::glue("{.x} ({round(.x/valid_total*100, 1)}%)")) # 单独统计两类非有效样本的数量 nc_count <- sum(var_col == "不适用", na.rm = T) miss_count <- sum(is.na(var_col)) # 拼接为gtsummary可识别的命名向量 all_stat <- c( valid_stat, "不适用" = as.character(nc_count), "缺失值" = as.character(miss_count) ) return(all_stat) } # 生成最终汇总表 tab |> tbl_summary( include = pregnant, label = list(pregnant = "是否怀孕"), statistic = list(pregnant = ~cat_stat_custom(data = pick(everything()), variable = cur_column())), missing = "no" # 关闭默认缺失值展示,避免重复统计 ) |> modify_footnote( rows = label %in% c("不适用", "缺失值"), columns = stat_0, footnote = "以上两类样本不纳入占比计算分母" )
这个方案相比此前尝试的两种方法优势明显:
- 不需要按适用人群拆分数据再用
tbl_stack()合并,只要所有题目的「不适用」取值统一用相同标签,这套自定义函数可以直接复用到所有分类变量,哪怕题量很大也只需要一次配置。 - 占比计算严格符合统计规则,「不适用」和缺失值都不会进入分母,也不会混在有效回答的分类里。
- 两类非有效回答的样本量会作为独立行展示,信息完整。
如果需要做分组统计,只需要在tbl_summary()中传入by参数,微调自定义函数适配分组计算逻辑即可,核心框架不需要改动;如果是连续变量需要做同类处理,只需要修改自定义函数里的有效样本统计逻辑,在输出里追加两类非有效样本的计数行就行。
注意:编码「不适用」取值时,不要和题目本身的有效回答选项重名,避免统计时混淆。
内容的提问来源于stack exchange,提问作者Claustre
相关产品推荐
相关产品推荐

