You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

R语言计算绘制累计发病率(含95%CI)及生存分析适用性咨询

嘿,针对你的问题,我来拆解一下生存分析的适用性,再给出具体的R代码方案~

生存分析的适用性判断

首先明确:累计发病率(IR)本质是固定随访期内新发病例占暴露人群的比例,而生存分析(尤其是Kaplan-Meier法)计算的是累计发病风险——当随访时间一致、无失访时,两者几乎等价;但如果存在失访、个体随访时间差异大的情况,生存分析能更准确地估计发病风险,因为它会对失访个体进行删失处理。

所以:

  • 如果你的数据是个体水平的随访数据(包含每个研究对象的入组时间、随访终止时间、是否发病、失访状态等),生存分析完全适用,且是更严谨的选择。
  • 如果你的数据是汇总统计数据(已经整理好各组的发病数、人年数/暴露人数),直接用流行病学方法计算IR和CI会更高效,不需要用到生存分析。

对于D2的基线现患情况:生存分析可以通过标记基线已发病的个体,但如果只是需要图表不从0开始,更简单的方式是在计算中加入基线现患率,直接调整可视化的y轴起点即可。

R包与代码实现

我会分两种数据类型(汇总数据/个体数据)给出方案,同时覆盖D1和D2的需求。

所需包

先安装并加载必要的包:

install.packages(c("epiR", "ggplot2", "dplyr", "survival", "survminer"))
library(epiR)
library(ggplot2)
library(dplyr)
library(survival)
library(survminer)

方案1:汇总数据(D1示例)

假设你的D1是长格式汇总数据,包含分组、事件类型、发病数、人年数:

步骤1:模拟/准备数据

set.seed(123) # 固定随机种子,方便复现
D1 <- expand.grid(group = paste0("G", 1:5), event = paste0("E", 1:8)) %>%
  mutate(
    cases = sample(5:20, nrow(.), replace = TRUE), # 发病数
    person_years = sample(800:1500, nrow(.), replace = TRUE) # 随访人年数
  )

步骤2:计算IR与95%CI

epiR包的epi.incidence函数,基于泊松分布计算置信区间:

D1_ir <- D1 %>%
  rowwise() %>%
  mutate(
    # 计算每1000人年的发病率,方便解读
    incidence = epi.incidence(cases, person_years, method = "poisson")$est * 1000,
    ir_lower = epi.incidence(cases, person_years, method = "poisson")$lower * 1000,
    ir_upper = epi.incidence(cases, person_years, method = "poisson")$upper * 1000
  ) %>%
  ungroup()

步骤3:分组绘制IR图表

为每个人群组单独生成图表,展示8类事件的IR及CI:

# 批量生成图表
plots_D1 <- D1_ir %>%
  group_by(group) %>%
  group_map(function(data, group_info) {
    ggplot(data, aes(x = event, y = incidence)) +
      geom_col(fill = "#2c3e50", width = 0.7) +
      geom_errorbar(aes(ymin = ir_lower, ymax = ir_upper), width = 0.2) +
      labs(
        title = paste("累计发病率(每1000人年) - 组", group_info$group),
        x = "事件类型",
        y = "累计发病率(95%CI)"
      ) +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, hjust = 1))
  })

# 查看第一组的图表
plots_D1[[1]]

方案2:汇总数据(D2示例,含基线现患)

假设D2在D1的基础上,增加了基线现患病例数和基线暴露人数:

步骤1:模拟/准备数据

set.seed(456)
D2 <- expand.grid(group = paste0("G", 1:5), event = paste0("E", 1:8)) %>%
  mutate(
    cases = sample(5:20, nrow(.), replace = TRUE),
    person_years = sample(800:1500, nrow(.), replace = TRUE),
    prev_cases = sample(2:10, nrow(.), replace = TRUE), # 基线现患数
    prev_n = person_years # 假设基线暴露人数与随访人数一致,可根据实际调整
  )

步骤2:计算调整后的病例率

我们计算基线患病率 + 随访累计发病率,并保留随访IR的置信区间:

D2_ir <- D2 %>%
  rowwise() %>%
  mutate(
    prev_rate = (prev_cases / prev_n) * 1000, # 每1000人的基线患病率
    incidence = epi.incidence(cases, person_years, method = "poisson")$est * 1000,
    ir_lower = epi.incidence(cases, person_years, method = "poisson")$lower * 1000,
    ir_upper = epi.incidence(cases, person_years, method = "poisson")$upper * 1000,
    total_rate = prev_rate + incidence # 总病例率(现患+新增)
  ) %>%
  ungroup()

步骤3:绘制非零起点的图表

图表y轴从基线患病率附近开始,同时标注基线现患的参考线:

plots_D2 <- D2_ir %>%
  group_by(group) %>%
  group_map(function(data, group_info) {
    ggplot(data, aes(x = event, y = total_rate)) +
      geom_col(fill = "#e74c3c", width = 0.7) +
      geom_errorbar(aes(ymin = prev_rate + ir_lower, ymax = prev_rate + ir_upper), width = 0.2) +
      geom_hline(aes(yintercept = prev_rate), linetype = "dashed", color = "#95a5a6", size = 0.8) +
      labs(
        title = paste("累计病例率(含基线现患) - 组", group_info$group),
        x = "事件类型",
        y = "累计病例率(每1000人,95%CI)"
      ) +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
      # 手动设置y轴范围,确保基线现患线可见
      ylim(min(data$prev_rate)*0.8, max(data$total_rate + data$ir_upper)*1.1)
  })

# 查看第一组的图表
plots_D2[[1]]

方案3:个体水平数据(生存分析实现)

如果你的数据是个体水平(每行一个研究对象),用survival包计算累计发病风险:

示例数据

# 模拟个体数据:group, event(是否发生E1), time(随访时间), status(1=发病,0=失访/未发病)
set.seed(789)
D1_individual <- expand.grid(group = paste0("G", 1:5), id = 1:200) %>%
  mutate(
    time = sample(1:10, nrow(.), replace = TRUE),
    status = rbinom(nrow(.), 1, 0.1) # 10%的发病概率
  )

计算累计发病风险(KM法)

# 按分组和事件(这里以E1为例,多事件可循环处理)
km_fit <- survfit(Surv(time, status) ~ group, data = D1_individual)

# 绘制KM曲线(即累计发病风险曲线)
ggsurvplot(
  km_fit,
  data = D1_individual,
  conf.int = TRUE, # 显示95%CI
  risk.table = TRUE, # 显示风险人数表
  title = "累计发病风险(E1) - 各人群组",
  xlab = "随访时间",
  ylab = "累计发病风险"
)

对于多事件(E1-E8),可以通过循环为每个事件单独计算并绘图。


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

火山引擎 最新活动