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

如何用R语言MatchIt包基于年龄与多ICD10编码匹配病例与对照

问题:基于多ICD10编码和年龄的病例对照匹配(MatchIt包)

需求说明

需要使用R语言的MatchIt包为病例患者匹配对照,要求:

  • 对照与病例年龄完全一致
  • 对照的ICD10编码至少包含病例的所有ICD10编码(对照可拥有更多编码)

当前问题:单个患者对应多条ICD10编码记录,现有匹配逻辑会按单条ICD记录分别匹配,导致病例匹配到多个仅满足部分ICD条件的对照,而非同时满足所有ICD条件的目标对照。

数据示例

library(tibble)
df <- tribble(
  ~patient_id, ~diagnosis, ~age, ~status,
  1001, "Z34", 20, "case",
  1001, "A24", 20, "case",
  1002, "N39", 22, "case",
  1002, "Z3A", 22, "case",
  1003, "N89", 23, "case",
  1003, "Z34", 23, "case",
  1004, "Z34", 20, "control",
  1004, "A24", 20, "control",
  1005, "D50", 23, "control",
  1005, "F41", 23, "control",
  1005, "N89", 23, "control",
  1005, "Z11", 23, "control",
  1005, "Z34", 23, "control",
  1006, "Z12", 22, "control",
  1006, "Z34", 22, "control",
  1006, "N39", 22, "control",
  1007, "E66", 20, "control",
  1007, "Z11", 20, "control",
  1007, "Z12", 20, "control",
  1007, "Z34", 20, "control"
)

尝试的代码及问题

library(MatchIt)
library(dplyr)

m.out <- matchit(I(status == "case") ~ age, data = df,
                 exact = ~age + diagnosis,
                 method = "optimal",
                 distance = "glm", ratio = 1)

m.data <- match.data(m.out, subclass = "matched_id")
print(m.data)

问题:病例1001同时匹配了1007(仅含Z34)和1004(含Z34+A24),但我们只需要匹配同时包含病例所有ICD编码的1004。

解决方案

核心思路是先将数据按患者聚合,统一管理每个患者的ICD编码集合,再基于集合包含关系筛选合格对照,最后完成匹配。

步骤1:聚合患者数据

将每个患者的多条ICD记录合并为一行,存储其所有ICD编码的集合:

library(dplyr)
library(purrr)

# 聚合每个患者的ICD编码为集合
patient_data <- df %>%
  group_by(patient_id, age, status) %>%
  summarise(icd_codes = list(diagnosis), .groups = "drop") %>%
  mutate(icd_set = map(icd_codes, ~sort(.x))) # 排序后方便后续判断包含关系

步骤2:筛选合格对照

为每个病例筛选同年龄且ICD集合包含病例所有编码的对照:

# 分离病例和对照数据集
cases <- patient_data %>% filter(status == "case")
controls <- patient_data %>% filter(status == "control")

# 为每个病例匹配符合条件的对照
matched_pairs <- cases %>%
  rowwise() %>%
  mutate(
    eligible_controls = list(
      controls %>%
        filter(age == !!age) %>%
        filter(map_lgl(icd_set, ~all(!!icd_set %in% .x))) %>%
        pull(patient_id)
    )
  ) %>%
  ungroup()

# 查看每个病例的合格对照列表
print(matched_pairs)

步骤3:完成匹配并整合数据

从合格对照中选择匹配对象(示例为随机选1个,也可根据需求用最优匹配逻辑),并整合回原始数据:

# 为每个病例分配1个合格对照(无合格对照则标记为NA)
final_matches <- matched_pairs %>%
  rowwise() %>%
  mutate(matched_control = ifelse(length(eligible_controls) > 0, 
                                  sample(eligible_controls, 1), 
                                  NA)) %>%
  ungroup() %>%
  select(patient_id, matched_control, age)

# 整合回原始数据,查看匹配后的所有记录
matched_data <- df %>%
  filter(patient_id %in% c(final_matches$patient_id, final_matches$matched_control)) %>%
  left_join(final_matches, by = c("patient_id", "age"))

print(matched_data)

扩展说明

  • 如果需要使用MatchIt的专业匹配算法(如最优匹配、卡钳匹配),可基于筛选出的合格对照池,在matchit函数中通过subclass或自定义距离函数实现更精准的匹配控制。
  • 若需匹配多个对照,只需调整sample函数的参数或改用MatchIt的ratio参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:23:23