如何在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
相关产品推荐
相关产品推荐

