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

定制tern/R包:按SOC-PT分组统计AE并展示患者占比

解决方案

要实现“发生该AE的患者数/组内总患者数”的展示形式,需要从统计逻辑自定义和列标签调整两部分入手,具体实现如下:

1. 核心思路

  • 替换默认的count_occurrences函数,改用自定义统计逻辑计算每组内发生特定AE的患者数,同时关联adsl中的组总患者数,拼接成n/N格式
  • 移除默认的show_colcounts,直接将组总患者数嵌入列标题,明确分母含义

2. 完整实现代码

library(pharmaverseadam)
library(tern)
library(dplyr)

adsl <- adsl %>%
  df_explicit_na()

adae <- adae %>%
  df_explicit_na() %>%
  var_relabel(
    AEBODSYS = "MedDRA System Organ Class",
    AEDECOD = "MedDRA Preferred Term"
  ) %>%
  filter(SAFFL == "Y")

# 提前计算各组总患者数,用于列标签和统计分母
get_group_totals <- function(df) {
  df %>%
    group_by(ACTARM) %>%
    summarise(N = n_distinct(USUBJID)) %>%
    bind_rows(tibble(ACTARM = "All Patients", N = n_distinct(df$USUBJID)))
}

group_totals <- get_group_totals(adsl)
arm_labels <- paste0(group_totals$ACTARM[1:nlevels(adsl$ACTARM)], " (N=", group_totals$N[1:nlevels(adsl$ACTARM)], ")")
overall_label <- paste0("All Patients (N=", group_totals$N[nrow(group_totals)], ")")

# 自定义统计函数:输出"发生AE患者数/组总患者数"格式
stat_ae_n_over_N <- function(x, .N) {
  n <- length(unique(x))
  list(ratio = paste0(n, "/", .N))
}

split_fun <- drop_split_levels

lyt <- basic_table() %>%
  # 替换列标签为带总患者数的格式
  split_cols_by(var = "ACTARM", labels = arm_labels) %>%
  add_overall_col(label = overall_label) %>%
  # 顶部AE汇总统计改为n/N格式
  analyze_num_patients(
    vars = "USUBJID",
    .stats = "unique",
    .labels = c(unique = "Total patients with at least one adverse event"),
    .formats = c(unique = function(x, .N) paste0(x, "/", .N)),
    .extra_args = list(.N = group_totals$N)
  ) %>%
  split_rows_by(
    "AEBODSYS",
    child_labels = "visible",
    nested = FALSE,
    split_fun = split_fun,
    label_pos = "topleft",
    split_label = obj_label(adae$AEBODSYS)
  ) %>%
  # SOC层级统计改为n/N格式
  summarize_num_patients(
    var = "USUBJID",
    .stats = "unique",
    .labels = c(unique = "Total patients with at least one adverse event"),
    .formats = c(unique = function(x, .N) paste0(x, "/", .N)),
    .extra_args = list(.N = group_totals$N)
  ) %>%
  # 替换count_occurrences,用自定义函数实现PT层级的n/N展示
  analyze_vars(
    vars = "AEDECOD",
    var_labels = obj_label(adae$AEDECOD),
    .stats = "ratio",
    .labels = c(ratio = ""),
    .indent_mods = 1L,
    .fun = stat_ae_n_over_N,
    .extra_args = list(.N = group_totals$N)
  )

result <- build_table(lyt, df = adae, alt_counts_df = adsl)

result

3. 关键修改说明

  • 列标签优化:通过get_group_totals从adsl提取每组总患者数,直接将(N=xxx)嵌入列标题,替代默认的列计数展示
  • 统计逻辑统一:从顶部汇总、SOC层级到PT层级,全部使用自定义函数输出n/N格式,确保表格逻辑一致
  • 参数传递:通过.extra_args将组总患者数传递给统计函数,保证分母是每组的全部患者数,而非仅发生AE的患者数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 17:23:15