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

如何为tbl_svysummary添加Cohen's D和Cramer's V效应量估计?

在tbl_svysummary中添加Cohen's D和Cramer's V效应量估计

问题根源

你之前在tbl_summary中使用的效应量函数是针对原始非加权数据编写的,但tbl_svysummary的add_stat传入的是survey::svydesign调查设计对象,而非普通data.frame,直接调用处理原始数据的函数自然会失效。

解决方案:编写加权效应量函数

需要基于调查设计对象,使用survey包工具计算加权后的统计量,进而推导效应量:

1. 加权Cohen's D(连续变量)

手动实现加权版本的Cohen's D,利用svymean和svyvar提取分组加权均值、方差,再结合加权样本量计算合并标准差:

my_weighted_cohens_d <- function(data, variable, by, ...) {
  # 计算分组加权均值与方差
  mean_by <- survey::svymean(as.formula(glue::glue("{variable} ~ {by}")), data = data)
  var_by <- survey::svyvar(as.formula(glue::glue("{variable} ~ {by}")), data = data)
  
  # 提取分组统计量
  m1 <- coef(mean_by)[[1]]
  m2 <- coef(mean_by)[[2]]
  sd1 <- sqrt(coef(var_by)[[1]])
  sd2 <- sqrt(coef(var_by)[[2]])
  
  # 计算分组加权样本量
  n1 <- survey::svytotal(~1, subset(data, data$variables[[by]] == levels(data$variables[[by]])[1]))
  n2 <- survey::svytotal(~1, subset(data, data$variables[[by]] == levels(data$variables[[by]])[2]))
  
  # 计算合并标准差与Cohen's D
  pooled_sd <- sqrt(((n1 - 1)*sd1^2 + (n2 - 1)*sd2^2)/(n1 + n2 - 2))
  d <- abs(m1 - m2)/pooled_sd
  
  round(d, 3)
}

2. 加权Cramer's V(分类变量)

基于加权列联表计算卡方值,再推导Cramer's V:

my_weighted_cramer_v <- function(data, variable, by, ...) {
  # 生成加权列联表
  tbl <- survey::svytable(as.formula(glue::glue("{variable} ~ {by}")), data = data)
  # 计算加权卡方检验
  chisq_test <- survey::svy_chisq(tbl)
  chi2 <- chisq_test$statistic
  
  # 计算Cramer's V
  n <- sum(tbl)
  min_dim <- min(dim(tbl)) - 1
  v <- sqrt(chi2 / (n * min_dim))
  
  round(v, 3)
}

完整可运行代码

library(tidyverse)
library(gtsummary)
library(survey)
library(glue)

# 定义加权效应量函数
my_weighted_cohens_d <- function(data, variable, by, ...) {
  mean_by <- survey::svymean(as.formula(glue::glue("{variable} ~ {by}")), data = data)
  var_by <- survey::svyvar(as.formula(glue::glue("{variable} ~ {by}")), data = data)
  
  m1 <- coef(mean_by)[[1]]
  m2 <- coef(mean_by)[[2]]
  sd1 <- sqrt(coef(var_by)[[1]])
  sd2 <- sqrt(coef(var_by)[[2]])
  
  n1 <- survey::svytotal(~1, subset(data, data$variables[[by]] == levels(data$variables[[by]])[1]))
  n2 <- survey::svytotal(~1, subset(data, data$variables[[by]] == levels(data$variables[[by]])[2]))
  
  pooled_sd <- sqrt(((n1 - 1)*sd1^2 + (n2 - 1)*sd2^2)/(n1 + n2 - 2))
  d <- abs(m1 - m2)/pooled_sd
  
  round(d, 3)
}

my_weighted_cramer_v <- function(data, variable, by, ...) {
  tbl <- survey::svytable(as.formula(glue::glue("{variable} ~ {by}")), data = data)
  chisq_test <- survey::svy_chisq(tbl)
  chi2 <- chisq_test$statistic
  
  n <- sum(tbl)
  min_dim <- min(dim(tbl)) - 1
  v <- sqrt(chi2 / (n * min_dim))
  
  round(v, 3)
}

# 生成带效应量的汇总表
tbl_svysummary_ex1 <- 
  survey::svydesign(~1, data = as.data.frame(Titanic), weights = ~Freq) %>% 
  tbl_svysummary(by = Survived, percent = "row", include = c(Class, Age)) %>% 
  add_p(test = list(all_categorical() ~ "svy.chisq.test")) %>% 
  add_stat(
    fns = list(all_continuous() ~ my_weighted_cohens_d,
               all_categorical() ~ my_weighted_cramer_v)) %>% 
  modify_header(add_stat_1 ~ "**Effect size**")

# 查看结果
tbl_svysummary_ex1

注意事项

  • 上述Cohen's D函数默认假设分组变量为二分类,若需支持多分类,需调整均值、方差的提取逻辑。
  • 所有统计量计算均基于调查加权逻辑,符合复杂抽样数据的分析要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:45:31