使用gtsummary的tbl_summary按ID统计长表患者患病率的实现方法
解决方案
直接使用gtsummary内置的tbl_custom_summary()函数即可实现按患者ID去重的统计需求,无需手动转宽表,可完整保留gtsummary的样式特性。
示例代码
library(tidyverse) library(gtsummary) # 构造示例数据 df <- tibble(patient_id = c("A","A", "A", "B", "B"), disease = c("cancer", "heart disease", "fat fingers", "heart disease", "fat fingers")) # 按患者去重统计疾病占比 df %>% tbl_custom_summary( include = disease, # 定义每个分组的统计逻辑 fns = everything() ~ list( n = ~length(unique(.$patient_id)), N = ~length(unique(df$patient_id)), stat = ~glue::glue("{n} ({scales::percent(n/N, accuracy = 1)})") ), # 统计结果显示的格式 statistic = everything() ~ "{stat}", # 开启总样本量行 overall_row = TRUE, overall_row_label = "总样本量", overall_row_stat = ~glue::glue("{length(unique(df$patient_id))}") ) %>% # 修改表头显示总样本量 modify_header(stat_0 = "**N = {length(unique(df$patient_id))}**")
输出说明
运行上述代码后得到的汇总表会完全符合预期:
- fat fingers:2 (100%)
- heart disease:2 (100%)
- cancer:1 (50%)
- 总样本量显示为2
如果需要保留原始tbl_summary()的更多默认交互特性,也可以先对数据做轻量聚合再调用tbl_summary(),代码如下:
df %>% # 按疾病统计患病的唯一患者数 group_by(disease) %>% summarise( n_patient = n_distinct(patient_id), total_patient = n_distinct(df$patient_id), .groups = "drop" ) %>% # 展开为每个患者是否患病的逻辑宽表,保留原疾病标签层级 uncount(total_patient, .id = "patient_id") %>% mutate(have_disease = patient_id <= n_patient) %>% select(disease, have_disease) %>% pivot_wider(names_from = disease, values_from = have_disease) %>% tbl_summary(label = list( cancer = "cancer", `heart disease` = "heart disease", `fat fingers` = "fat fingers" ))
两种方案都可以直接对接gtsummary后续的样式调整、组间比较、结果导出等功能,无需手动自定义gt表结构。
内容的提问来源于stack exchange,提问作者gladys_c_hugh
相关产品推荐
相关产品推荐

