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

如何让gtsummary基于ITime类型正确展示时间统计量?

问题描述

我有POSIXct格式的医院入院时间(例如"1899-12-31 13:11:00"),无需关注日期,因此用lubridate包提取时分秒并格式化为%H:%M:%S,再转换为ITime类型(该类型以当日秒数整数存储),方便计算入院时间的均值、中位数、最值等统计量。

单独计算统计量时结果正常,比如执行mean(sample_data$HOSP_ADMSN_TIME.x)会输出预期的"14:11:18"。但将该变量传入gtsummary生成汇总表时,它把变量视为连续变量,均值显示为57078(秒数)而非预期的时间格式。

核心需求:让gtsummary基于ITime类型处理时间戳,计算并展示正确格式的统计量。


示例数据集

# A tibble: 10 × 1
   HOSP_ADMSN_TIME.x  
   <dttm>             
 1 2021-04-19 10:00:00
 2 2021-05-02 09:18:00
 3 2021-09-09 15:06:00
 4 2021-08-17 13:10:00
 5 2022-01-18 11:44:00
 6 2021-10-13 20:33:00
 7 2021-05-06 19:09:00
 8 2021-08-04 12:49:00
 9 2021-11-15 11:00:00
10 2021-09-01 19:04:00

数据处理代码

sample_data$HOSP_ADMSN_TIME.x <- format(ymd_hms(sample_data$HOSP_ADMSN_TIME.x), "%H:%M:%S")
sample_data$HOSP_ADMSN_TIME.x <- as.ITime(sample_data$HOSP_ADMSN_TIME.x)

验证统计量计算

mean(sample_data$HOSP_ADMSN_TIME.x)
[1] "14:11:18"

当前gtsummary汇总表代码

sample_data %>%
  tbl_summary(
    label = list(HOSP_ADMSN_TIME.x ~ "Hospital Admission Time"),
    missing = "ifany",
    missing_text = "Missing",
    type = HOSP_ADMSN_TIME.x ~ "continuous2",
    statistic = HOSP_ADMSN_TIME.x ~ c("{mean}",
                                        "{median} ({p25}, {p75})",
                                        "{min}, {max}")
  ) %>%
  bold_labels() %>%
  modify_header(label ~ "**Variable**")

(当前生成的表格中均值显示为57,078而非预期时间格式)


解决方案

gtsummary默认会读取ITime类型变量的底层存储值(秒数整数)来生成统计量,因此需要通过自定义逻辑将计算结果转回时间格式,以下是三种可行方法:

方法1:自定义统计表达式

直接在statistic参数中使用自定义表达式,计算后将秒数结果转换为ITime格式再输出:

sample_data %>%
  tbl_summary(
    label = list(HOSP_ADMSN_TIME.x ~ "Hospital Admission Time"),
    missing = "ifany",
    missing_text = "Missing",
    type = HOSP_ADMSN_TIME.x ~ "continuous2",
    statistic = HOSP_ADMSN_TIME.x ~ list(
      ~ as.character(as.ITime(mean(.x))),
      ~ sprintf("%s (%s, %s)", 
                as.character(as.ITime(median(.x))),
                as.character(as.ITime(quantile(.x, 0.25))),
                as.character(as.ITime(quantile(.x, 0.75)))),
      ~ sprintf("%s, %s", 
                as.character(as.ITime(min(.x))),
                as.character(as.ITime(max(.x))))
    )
  ) %>%
  bold_labels() %>%
  modify_header(label ~ "**Variable**")

方法2:提前计算统计量再传入

手动计算所有需要的统计量,直接将格式化后的结果传入statistic参数,适合需要精细控制的场景:

# 预先计算并格式化统计量
time_stats <- list(
  mean = as.character(as.ITime(mean(sample_data$HOSP_ADMSN_TIME.x))),
  median_iqr = sprintf("%s (%s, %s)", 
                       as.character(as.ITime(median(sample_data$HOSP_ADMSN_TIME.x))),
                       as.character(as.ITime(quantile(sample_data$HOSP_ADMSN_TIME.x, 0.25))),
                       as.character(as.ITime(quantile(sample_data$HOSP_ADMSN_TIME.x, 0.75)))),
  min_max = sprintf("%s, %s", 
                    as.character(as.ITime(min(sample_data$HOSP_ADMSN_TIME.x))),
                    as.character(as.ITime(max(sample_data$HOSP_ADMSN_TIME.x))))
)

# 生成汇总表
sample_data %>%
  tbl_summary(
    label = list(HOSP_ADMSN_TIME.x ~ "Hospital Admission Time"),
    missing = "ifany",
    missing_text = "Missing",
    type = HOSP_ADMSN_TIME.x ~ "continuous2",
    statistic = HOSP_ADMSN_TIME.x ~ c(time_stats$mean, time_stats$median_iqr, time_stats$min_max)
  ) %>%
  bold_labels() %>%
  modify_header(label ~ "**Variable**")

方法3:注册ITime类型的全局处理规则

如果需要频繁处理ITime变量,可以注册一个gtsummary的全局统计函数,让它自动识别并格式化ITime类型的统计结果:

# 注册自定义统计函数
register_statistic(
  fn = function(data, variable, ...) {
    x <- data[[variable]]
    tibble(
      label = c("Mean", "Median (IQR)", "Min, Max"),
      stat = c(
        as.character(as.ITime(mean(x))),
        sprintf("%s (%s, %s)", 
                as.character(as.ITime(median(x))),
                as.character(as.ITime(quantile(x, 0.25))),
                as.character(as.ITime(quantile(x, 0.75)))),
        sprintf("%s, %s", 
                as.character(as.ITime(min(x))),
                as.character(as.ITime(max(x))))
      )
    )
  },
  type = "continuous",
  class = "ITime"
)

# 之后直接调用tbl_summary即可自动处理ITime变量
sample_data %>%
  tbl_summary(
    label = list(HOSP_ADMSN_TIME.x ~ "Hospital Admission Time"),
    missing = "ifany",
    missing_text = "Missing"
  ) %>%
  bold_labels() %>%
  modify_header(label ~ "**Variable**")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 18:34:54