You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

关键修改说明

  1. 函数直接使用add_stat传入的svydesign对象,避免全局变量依赖,确保结果准确。
  2. 移除pull操作,始终保持数据框结构,保证后续的列选择和格式化操作正常执行。
  3. 针对svyquantile的返回列名格式(变量名.分位数),精准重命名列,确保add_stat能正确识别并插入表格。
  4. 新增表头修改步骤,让表格可读性更强。

内容的提问来源于stack exchange,提问作者Anthony Romero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:47:13