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

如何在gtsummary的tbl_svysummary/tbl_summary中使百分比凑整至100%

问题描述

我已掌握针对向量和表格的百分比凑整至100%的通用方案,但尚未找到在gtsummary包的tbl_svysummary()或tbl_summary()函数中的实现方法。我拥有一个包含分类变量和数值变量的加权dataframe(示例代码如下),需要获取比例和均值,但希望分类变量的各比例总和恰好为100%(而非99%或101%),且百分比保留0位或2位小数,请问是否有可行方法?

示例代码:

library(dplyr)
library(gtsummary)    
set.seed(123)

numerical_var <- rnorm(200, mean = 50, sd = 10)
categories <- c("Category_A", "Category_B", "Category_C", "Category_D")
categorical_var1 <- sample(categories, 200, replace = TRUE)
categorical_var2 <- sample(categories, 200, replace = TRUE)
categorical_var3 <- sample(categories, 200, replace = TRUE)
weight_var <- runif(200, min = 0.003, max = 40)

# Create the data frame
df<- data.frame(
  num = numerical_var,
  cat1 = categorical_var1,
  cat2 = categorical_var2,
  cat3  = categorical_var3,
  wgt = weight_var
)

# Create design object 
svy_design <- survey::svydesign(
  ~1, 
  data = df, 
  weights = ~wgt
)

# Get frequencies 
svy_table <- svy_design %>%
  tbl_svysummary(
    by = cat1,
    statistic = all_categorical() ~ "{p}%"
  ) %>%
  add_p(
    group = cat1
  )

svy_table %>%
  gtsummary::as_tibble() %>% 
  writexl::write_xlsx(
    ., "test.xlsx"
  )
可行解决方案

方法1:自定义统计函数实现凑整

先实现一个能保证百分比总和为100%的凑整函数,再在tbl_svysummary()中指定使用该函数计算分类变量的百分比:

# 定义百分比凑整函数:保证总和为100%
round_pct <- function(x, digits = 0) {
  pct <- x / sum(x) * 100
  rounded <- round(pct, digits)
  diff <- 100 - sum(rounded)
  
  if (diff != 0) {
    # 将差值调整到与原始百分比偏差最大的项上
    idx <- which.max(abs(pct - rounded))
    rounded[idx] <- rounded[idx] + diff
  }
  paste0(rounded, "%")
}

# 在tbl_svysummary中使用自定义统计量
svy_table <- svy_design %>%
  tbl_svysummary(
    by = cat1,
    statistic = list(
      all_categorical() ~ "{round_pct(stat)}",
      all_continuous() ~ "{mean} ({sd})"
    ),
    digits = all_categorical() ~ 0  # 这里设置小数位数,需2位则改为2
  ) %>%
  add_p(group = cat1)

方法2:表格生成后进行后处理

若不想修改统计计算流程,可在生成表格后转为tibble,再对百分比列进行调整:

# 导出原始表格为tibble
svy_tbl <- svy_table %>% gtsummary::as_tibble()

# 定义调整百分比总和的函数
adjust_pct_sum <- function(pct_col, digits = 0) {
  # 提取百分比中的数字部分
  pct_num <- as.numeric(sub("%", "", pct_col))
  # 计算与100%的差值
  diff <- 100 - sum(pct_num)
  
  if (diff != 0) {
    # 选择偏差最大的项进行调整
    idx <- which.max(abs(pct_num - round(pct_num, digits)))
    pct_num[idx] <- pct_num[idx] + diff
  }
  # 重新格式化为百分比字符串
  paste0(round(pct_num, digits), "%")
}

# 对所有统计列(以stat_开头)进行调整
adjusted_tbl <- svy_tbl %>%
  mutate(across(starts_with("stat_"), ~adjust_pct_sum(., digits = 0)))

# 导出调整后的表格
adjusted_tbl %>% writexl::write_xlsx("test_adjusted.xlsx")

关键说明

  • 若需保留2位小数,只需将两个方法中的digits参数改为2即可。
  • 加权数据场景下,gtsummary会自动使用加权频数计算比例,无需额外处理加权逻辑。
  • 调整逻辑采用“偏差最大项优先调整”的规则,是百分比凑整的通用做法,能最大程度保留原始比例的准确性。

内容的提问来源于stack exchange,提问作者blue-create

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:55:54