如何在tbl_svysummary中为分类变量行添加数值统计列?
在tbl_svysummary中为分类变量添加加权中位数列的修正方案
之前在Stack Overflow上看到用tbl_summary结合add_stat可以给分类变量的每个水平添加数值变量的均值列,现在想在tbl_svysummary(加权抽样数据场景)中实现类似功能——给分类变量每行添加数值变量的加权中位数,但自己写的代码没得到正确结果,相关代码如下:
原参考代码(tbl_summary场景)
library(gtsummary) fn_add_mean <- function(data, variable, ...) { data %>% dplyr::group_by(.data[[variable]]) %>% dplyr::arrange(.data[[variable]]) %>% dplyr::summarise(hp = mean(hp, na.rm = TRUE)) %>% select(hp) %>% mutate(hp = style_sigfig(hp)) } fn_add_mean(mtcars, "cyl") #> # A tibble: 3 x 1 #> hp #> <chr> #> 1 83 #> 2 122 #> 3 209 tbl <- mtcars %>% select(hp, cyl, gear) %>% tbl_summary( include = -hp, type = everything() ~ "categorical" ) %>% add_stat( all_categorical() ~ fn_add_mean, location = all_categorical() ~ "level" ) %>% modify_header(hp ~ "**Mean Horsepower**")
我的尝试代码(未成功)
fn_add_median <- function(data, variable, ...) { sampling_design <- svydesign(ids = ~1, weights = ~wt, data = endes_data) data |> svyby(~v133, .data[[variable]], design = sampling_design, FUN = svyquantile, quantiles = 0.5) |> rename(med_years = quantiles) |> pull(med_years) |> select(med_years) |> mutate(med_years= style_sigfig(med_years)) } survey::svydesign(id = ~1, data = as.data.frame(endes_data), weights = ~wt) |> tbl_svysummary(by = education, percent = "row", digits = everything() ~ 1, include = c(age_cat, resid_area, region), statistic = all_categorical() ~ "{p}") |> bold_labels() |> add_stat(fns = all_categorical() ~ fn_add_median, location = all_categorical() ~ "level")
问题分析与修正方案
你的代码存在三个核心问题:
- 重复构建抽样设计且依赖全局变量:
add_stat传入的data已经是svydesign对象,无需用全局的endes_data重新创建,这会导致结果错误且函数复用性差。 - 数据处理流程断裂:
pull(med_years)会把数据转为向量,后续的select和mutate无法对向量操作,直接报错。 - 返回格式不符合要求:
add_stat要求函数返回与分类变量水平一一对应的单列数据框,你的处理破坏了这个结构。
修正后的完整代码
library(gtsummary) library(survey) library(dplyr) # 修正后的自定义中位数计算函数 fn_add_median <- function(data, variable, ...) { # 直接使用传入的svydesign对象,无需重新构建 svyby( formula = ~v133, by = .data[[variable]], design = data, FUN = svyquantile, quantiles = 0.5, ci = FALSE # 仅计算中位数,不需要置信区间 ) %>% # 提取中位数列并重命名(svyquantile返回的列名格式为"变量名.分位数") select(med_years = `v133.50%`) %>% # 格式化数值为指定格式 mutate(med_years = style_sigfig(med_years)) } # 构建抽样设计(仅需执行一次) survey_design <- svydesign(id = ~1, data = as.data.frame(endes_data), weights = ~wt) # 生成表格并添加加权中位数列 final_tbl <- survey_design %>% tbl_svysummary( by = education, percent = "row", digits = everything() ~ 1, include = c(age_cat, resid_area, region), statistic = all_categorical() ~ "{p}" ) %>% bold_labels() %>% add_stat( fns = all_categorical() ~ fn_add_median, location = all_categorical() ~ "level" ) %>% # 修改新增中位数列的表头 modify_header(med_years ~ "**加权中位数(v133)**") # 查看结果 final_tbl
关键修改说明
- 函数直接使用
add_stat传入的svydesign对象,避免全局变量依赖,确保结果准确。 - 移除
pull操作,始终保持数据框结构,保证后续的列选择和格式化操作正常执行。 - 针对
svyquantile的返回列名格式(变量名.分位数),精准重命名列,确保add_stat能正确识别并插入表格。 - 新增表头修改步骤,让表格可读性更强。
内容的提问来源于stack exchange,提问作者Anthony Romero
相关产品推荐
相关产品推荐

