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

基于长格式诊疗episode数据构建带日期的二元变量及多病共存分析

问题描述

我正在处理一份包含数十万人、约15年住院episode的临床数据表,表中每行对应一个episode,包含以下字段:

  • episode编号
  • episode日期(日期与episode编号未按时间顺序排列)
  • 56种目标诊断的二元指标(1表示该episode存在对应诊断,0表示不存在)

可复现的R语言示例数据如下:

df <- data.frame(
  id = c("1001", "1001", "1001", "1001", "1001", "1001", 
         "1002", "1002", "1002", "1002", "1002",
         "1003", "1003", "1003", "1003", "1003", "1003", "1003",
         "1005", "1005", "1005", "1005", "1005", "1005", "1005", "1005", "1005"),
  episode = c(0, 1, 2, 3, 4, 5,
              0, 1, 3, 4, 5,
              0, 2, 3, 6, 7, 9, 10,
              1, 2, 3, 4, 5, 6, 7, 8, 9),
  date = sample(seq(as.Date('2010/01/01'), as.Date('2016/01/01'), by="day"), 27),
  diag_a = c(1, 1, 0, 0, 1, 1,
             0, 0, 0, 0, 0,
             0, 0, 1, 1, 1, 1, 1,
             0, 0, 0, 0, 0, 0, 0, 0, 0),
  diag_b = c(0, 0, 0, 0, 0, 0,
             1, 1, 1, 1, 1,
             0, 0, 0, 0, 0, 0, 0,
             0, 0, 1, 0, 0, 0, 0, 0, 0),
  diag_c = c(1, 0, 0, 1, 0, 0,
             0, 0, 0, 0, 0,
             0, 0, 1, 1, 1, 1, 1,
             0, 0, 0, 0, 0, 0, 0, 0, 0),
  diag_d = c(1, 1, 0, 0, 1, 1,
             0, 0, 0, 0, 0,
             0, 0, 1, 1, 1, 1, 1,
             0, 0, 0, 0, 1, 0, 0, 0, 0)
)

需要实现以下需求:

  1. 识别每个ID是否出现过56种诊断中的任意一种,并提取每种诊断的最早确诊日期;
  2. 创建multimorbidity二元列(0/1),标记参与者是否存在2种及以上目标诊断,并生成首次达到多病共存的日期(即第二种目标诊断出现的日期,可能在同一episode内);
  3. 为每个ID统计出现的目标诊断数量,生成condition_count列。

核心需求是获取每个ID的多病共存状态及首次发生日期,用于后续回归分析。

解决方案

使用tidyverse工具链处理,代码逻辑清晰且适合大规模数据:

首先加载依赖包:

library(tidyverse)

步骤1:提取各诊断最早日期及是否有任一诊断

先把宽格式的诊断列转成长格式,筛选出有诊断的记录,按ID和诊断分组取最早日期,再转回宽格式,最后标记是否存在至少一种诊断:

diagnosis_dates <- df %>%
  pivot_longer(cols = starts_with("diag_"), names_to = "diagnosis", values_to = "present") %>%
  filter(present == 1) %>%
  group_by(id, diagnosis) %>%
  summarise(first_diagnosis_date = min(date), .groups = "drop") %>%
  pivot_wider(id_cols = id, names_from = diagnosis, values_from = first_diagnosis_date) %>%
  mutate(any_diagnosis = if_else(rowSums(!is.na(select(., starts_with("diag_")))) > 0, 1, 0))

步骤2&3:计算诊断数量、多病共存状态及首次日期

先按ID和日期排序(确保时间顺序正确),然后逐行累计每个ID已出现的诊断种类,找到首次达到2种的日期;再统计每个ID的总诊断数,最后合并并补全缺失值:

multimorbidity_data <- df %>%
  arrange(id, date) %>%
  group_by(id) %>%
  # 计算截至当前行的累计诊断种类数
  mutate(
    cumulative_conditions = pmap_int(seq(n()), function(i) {
      slice(cur_data(), 1:i) %>%
        select(starts_with("diag_")) %>%
        summarise(across(everything(), max)) %>% # 取每个诊断是否在之前出现过
        pivot_longer(everything()) %>%
        filter(value == 1) %>%
        nrow()
    })
  ) %>%
  # 筛选首次达到2种及以上诊断的记录
  filter(cumulative_conditions >= 2) %>%
  slice(1) %>%
  select(id, first_multimorbidity_date = date) %>%
  # 合并总诊断数量数据
  left_join(
    df %>%
      pivot_longer(cols = starts_with("diag_"), names_to = "diagnosis", values_to = "present") %>%
      filter(present == 1) %>%
      distinct(id, diagnosis) %>%
      group_by(id) %>%
      summarise(condition_count = n(), .groups = "drop"),
    by = "id"
  ) %>%
  # 标记多病共存状态
  mutate(multimorbidity = if_else(condition_count >= 2, 1, 0)) %>%
  # 补全没有诊断或只有1种诊断的ID的缺失值
  right_join(distinct(df, id), by = "id") %>%
  mutate(
    condition_count = replace_na(condition_count, 0),
    multimorbidity = replace_na(multimorbidity, 0),
    first_multimorbidity_date = replace_na(first_multimorbidity_date, NA_Date_)
  )

合并所有结果

把步骤1和步骤2的结果合并,得到最终的ID级汇总表:

final_result <- diagnosis_dates %>%
  full_join(multimorbidity_data, by = "id")

# 查看结果
print(final_result)

这个方案能高效处理大规模数据,所有操作都是向量化或分组操作,避免循环;同时准确处理了同一episode出现多种诊断的情况(累计数会直接统计为对应数量,首次日期取该episode的日期)。

内容的提问来源于stack exchange,提问作者L.Steell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:54:55