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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 22:42:46