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

如何在gtsummary自定义统计函数中获取其推断的真实变量类型?

如何在gtsummary自定义统计函数中获取实际变量类型?

gtsummary默认会将水平数≤10的变量(无论分类、数值还是字符型)视为因子变量并展示各水平统计量。我编写了一个自定义统计函数,对连续变量展示均值差,对因子变量展示各水平占比差。但当通过type参数强制指定某个变量为连续变量时,函数仍按自身逻辑生成多水平统计量,导致与gtsummary的处理结果出现维度不匹配错误。

示例代码

library(gtsummary)
library(extraDistr)
library(tidyverse)
library(magrittr)
library(glue)
library(gtools)
library(forcats)

N <- 1000
toydf <- data.frame(
  # 数值变量,仅4个可能取值(0,1,2,3)
  children = rbinom(N, size = 3, prob = 0.5),
  # 数值变量,大量水平
  age = rdunif(N, 10, 100),
  # 因子变量,2个水平
  gender = sample(c("M", "F"), N, replace = TRUE),
  # 因子变量,20个水平
  human_type = sample(paste0("Type_", seq(1,20)), N, replace = TRUE)
)
toydf$age %<>% as.integer()
toydf$gender %<>% as.factor()
toydf$human_type %<>% as.factor()
toydf$human_type %<>% fct_relevel(mixedsort(levels(.)))

# 自定义统计函数:连续变量展示均值差,因子变量展示各水平占比差
my_mean_diff <- function(data, variable, by, tbl, ...) {
  
  x <- data[[variable]]
  g <- data[[by]]
  lvls <- levels(g)
  vartype <- class(x)[1]
  
  # 原逻辑:自行判断变量类型
  if(
    (vartype=="character" | vartype=="numeric" | vartype=="integer") &
    length(unique(x)) <= 10
  ) 
  {
    vartype <- "factor"
  }
  
  print(paste0("Variable: ", variable, ", Type: ", vartype))
  
  switch(
    vartype,
    factor = {
      prop <- prop.table(table(x, g), margin = 2)
      return((prop[, lvls[2]] - prop[, lvls[1]]) * 100)
    },
    integer = {
      return(diff(tapply(x, g, mean, na.rm = TRUE)))
    },
    {
      stop(glue("ERROR: Unrecognized type {vartype}"))
    }
  )
}

# 默认情况下运行正常
toydf %>% 
  tbl_summary(
    by = "gender",
    percent = "column"
  ) %>% add_stat(
    fns = everything() ~ my_mean_diff,
    location = list(
      all_continuous() ~ "label",
      all_categorical() ~ "level",
      all_dichotomous() ~ "label"
    )
  ) 

错误场景

当通过type参数指定children为连续变量时,出现维度不匹配错误:

Error in `add_stat()`:
! Dimension of "children" and the added statistic do not match.
ℹ Expecting statistic/data frame to be length/no. rows 1.
Run `rlang::last_trace()` to see where the error occurred.

解决方案:从gtsummary元数据中获取实际变量类型

gtsummary生成tbl_summary对象后,会将变量的实际处理类型存储在tbl$meta_data中。我们可以直接读取这个元数据的type字段,替代自定义函数内的类型判断逻辑,确保与gtsummary的处理逻辑完全对齐。

修改后的自定义统计函数

my_mean_diff <- function(data, variable, by, tbl, ...) {
  
  x <- data[[variable]]
  g <- data[[by]]
  lvls <- levels(g)
  
  # 从gtsummary元数据中获取变量实际处理类型
  vartype <- tbl$meta_data %>% 
    dplyr::filter(variable == !!variable) %>% 
    dplyr::pull(type)
  
  print(paste0("Variable: ", variable, ", Type: ", vartype))
  
  switch(
    vartype,
    categorical = {
      prop <- prop.table(table(x, g), margin = 2)
      return((prop[, lvls[2]] - prop[, lvls[1]]) * 100)
    },
    continuous = {
      return(diff(tapply(x, g, mean, na.rm = TRUE)))
    },
    {
      stop(glue("ERROR: Unrecognized type {vartype}"))
    }
  )
}

测试修改后的代码

指定children为连续变量,运行不再报错:

toydf %>% 
  tbl_summary(
    by = "gender",
    percent = "column",
    type = children ~ "continuous"  # 强制指定为连续变量
  ) %>% add_stat(
    fns = everything() ~ my_mean_diff,
    location = list(
      all_continuous() ~ "label",
      all_categorical() ~ "level",
      all_dichotomous() ~ "label"
    )
  ) 

说明

tbl$meta_data是gtsummary存储变量元信息的数据框,其中的type字段对应gtsummary实际处理该变量的类型("continuous"或"categorical")。通过直接读取这个值,自定义函数就能根据gtsummary的实际处理逻辑生成对应维度的统计量,避免维度不匹配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 21:07:29