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

如何按患者ID合并两个不等长DataFrame并基于日期匹配对应行?

解决不等长患者DataFrame按日期匹配合并的问题

我明白你遇到的问题了——直接用left_join按PatientID合并会因为同一个患者有多条X光记录导致笛卡尔积,出现重复行,还没法匹配到最接近的日期。结合你的需求,我们可以分步骤处理,精准实现目标合并:

第一步:统一日期格式(关键前提)

首先得把所有字符型的日期转换成R的Date类型,不然没法计算时间差找最近的记录。用lubridate包的dmy函数(适配日/月/年格式)最方便:

library(dplyr)
library(lubridate)

# 转换DfA的X光日期
DfA <- DfA %>%
  mutate(X-rayDate = dmy(X-rayDate))

# 转换DfB的手术日期和检测日期
DfB <- DfB %>%
  mutate(ProcDate = dmy(ProcDate),
         Test1Date = dmy(Test1Date),
         Test2Date = dmy(Test2Date))

第二步:给DfB标记时间点

你的DfB每行对应一个时间点(术前/术后早期/术后1年),我们先给每行打上标签,方便后续区分处理:

DfB <- DfB %>%
  group_by(PatientID) %>%
  mutate(TimePoint = case_when(
    # 假设第一行是术前,第二行术后早期,第三行术后1年;如果数据不按顺序,可改用日期差判断
    row_number() == 1 ~ "Pre-op",
    row_number() == 2 ~ "Post-op Early",
    row_number() == 3 ~ "Post-op 1Y"
  )) %>%
  ungroup()

如果你的数据不是按时间顺序排列的,可以替换成基于日期的判断逻辑,比如:

# 示例:用日期差判断时间点
TimePoint = case_when(
  Test1Date <= ProcDate ~ "Pre-op",
  between(Test1Date, ProcDate + days(1), ProcDate + months(3)) ~ "Post-op Early",
  between(Test1Date, ProcDate + months(11), ProcDate + months(13)) ~ "Post-op 1Y"
)

第三步:分情况合并数据

我们把术前和术后行分开处理,再合并到一起:

  1. 术前行处理:直接添加X光相关列并填充NA
  2. 术后行处理:为每行匹配同一患者下最接近检测日期的X光记录
# 处理术前行
pre_op_df <- DfB %>%
  filter(TimePoint == "Pre-op") %>%
  # 批量填充所有X光列为NA(适配你15项指标的场景)
  mutate(across(starts_with("X-ray"), ~NA))

# 处理术后行:匹配最接近的X光记录
post_op_df <- DfB %>%
  filter(TimePoint != "Pre-op") %>%
  group_by(PatientID, TimePoint) %>%
  mutate(
    # 找到当前患者下,X光日期与检测日期(这里用Test1Date作为参考)最接近的记录
    closest_xray = list(
      DfA %>%
        filter(PatientID == cur_data()$PatientID[1]) %>%
        mutate(date_diff = abs(X-rayDate - cur_data()$Test1Date[1])) %>%
        # 取时间差最小的那条,with_ties=FALSE确保只取一条(如果有多个相同差的)
        slice_min(date_diff, n = 1, with_ties = FALSE) %>%
        select(-PatientID, -date_diff)
    )
  ) %>%
  # 把匹配到的X光数据展开到当前行
  unnest(closest_xray) %>%
  ungroup()

# 合并术前+术后行,调整列顺序和目标一致
DfC <- bind_rows(pre_op_df, post_op_df) %>%
  select(PatientID, ProcDate, Test1, Test1Date, Test2, Test2Date, starts_with("X-ray"))

为什么之前的left_join会出问题?

直接按PatientID合并时,DfB的每一行会和DfA中该患者的所有X光记录合并,产生笛卡尔积(比如1条术后行+2条X光记录=2行重复数据),而且没有筛选最接近的日期,自然会出现数据混乱和丢失的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:37:36