使用table1()与t1kable()生成PDF报告表格时的两类问题:单水平因子显示异常及NA行小数位未按要求保留
解决table1()生成PDF表格的两个问题
问题1:单水平因子显示为"1"而非实际标签
这个问题的核心是:当因子只有一个水平时,table1()会默认把它当作连续变量处理,导致你的自定义my.render.cat函数完全没被调用。这里有两个简洁的解决思路:
方法1:强制指定变量为分类类型
在调用table1()时,通过type参数明确标记那些可能出现单水平的变量为分类类型,直接告诉函数该怎么处理它:
table1(strata, labels, render.categorical = my.render.cat, type = list(citizenship_status = "categorical")) # 强制指定为分类变量
如果你的多个数据集里还有其他可能出现单水平的变量,直接把它们都加到type列表里就行,比如type = list(citizenship_status = "categorical", other_var = "categorical")。
方法2:调整数据预处理逻辑(备选)
如果不想每次手动指定变量类型,可以在droplevels()后给单水平因子临时加一个空水平,后续表格生成时这个空水平会自动被忽略(但这个方法不如方法1直接):
df <- df %>% mutate(across(where(is.factor), function(x) { if(nlevels(x) == 1) { factor(x, levels = c(levels(x), "")) # 添加临时空水平 } else { x } }))
问题2:Missing行百分比未保留0位小数
你猜的没错,stats.default(x)只处理了非缺失的分类水平,缺失值的统计逻辑是单独在stats.missing(x)里的。只需要修改你的自定义渲染函数,把缺失值的格式也统一处理:
更新后的my.render.cat函数:
my.render.cat <- function(x) { # 处理非缺失的分类水平 non_missing <- sapply(stats.default(x), function(y) with(y, sprintf("%d (%.0f %%)", FREQ, PCT))) # 单独处理缺失值的统计格式 missing_stats <- stats.missing(x) missing_line <- if(missing_stats$FREQ > 0) { sprintf("%d (%.0f %%)", missing_stats$FREQ, missing_stats$PCT) } else { "" } # 组合所有结果,保持表格的行顺序 c("", non_missing, missing_line) }
完整修正后的代码
把两个方案整合到你的代码里,最终版本如下:
library(tidyverse) library(ggplot2) library(table1) library(kableExtra) # Create df for reproducible example df <- tibble(grad_term = c(rep("Fall '15 to Summer '20", 3), "Spring '12 to Summer '15",rep("Fall '15 to Summer '20", 5), "Spring '12 to Summer '15"), enrollment_age = c("23-29", "30-39", rep("23-29",8)), gender = c(rep("Male", 6), rep("Female", 2), rep("Male", 2)), racial_group = c("2+ groups", rep("White", 7), NA_character_, "White"), citizenship_status = c(rep("Since birth", 10)) ) %>% mutate(across(.cols = everything(), ~ factor(.x))) # Create necessary components of table1() object labels <- list( variables=list(gender="Gender", racial_group="Race/Ethnicity", citizenship_status="Citizenship Status", enrollment_age="Age at Enrollment", grad_term = "Graduation Term")) strata <- c(list(Total = df)) # 更新后的自定义渲染函数:覆盖分类水平和缺失值的格式 my.render.cat <- function(x) { non_missing <- sapply(stats.default(x), function(y) with(y, sprintf("%d (%.0f %%)", FREQ, PCT))) missing_stats <- stats.missing(x) missing_line <- if(missing_stats$FREQ > 0) { sprintf("%d (%.0f %%)", missing_stats$FREQ, missing_stats$PCT) } else { "" } c("", non_missing, missing_line) } # 调用table1时强制指定单水平变量为分类类型 table1(strata, labels, render.categorical = my.render.cat, type = list(citizenship_status = "categorical")) %>% t1kable() %>% kable_styling(., latex_options = "hold_position", position = "center")
这样两个问题就都解决了:单水平因子会显示正确的Since birth标签,Missing行的百分比也会统一保留0位小数。
内容的提问来源于stack exchange,提问作者Evan Dragich
相关产品推荐
相关产品推荐

