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

R语言按个体ID对应事件日期区间筛选随访记录的实现问题

问题解答

现有逻辑说明

你观察到的「ID为5的个体1988年12月15日的随访被匹配到2019年9月3日的事件,之后被过滤」是同ID多对多关联的正常表现:同一个体的每一条随访会和该个体的所有事件逐一匹配生成多行,过滤步骤仅会删除不满足对应事件时间区间的行。只要该随访落在任意一个事件的2年观测窗口内,就会有对应的匹配行被保留,不会出现有效记录被误删的问题。
如果你的需求是每个随访仅保留一条记录,可以在过滤后按visit_id去重即可,避免同一条随访落在多个事件窗口时出现重复行。

更高效的实现方案

你原有的先全量关联再过滤的方案,在随访数据量极大时会生成非常多的无效中间匹配行,占用过多内存、运行效率低。可以直接使用非等值连接在关联阶段就完成时间区间的筛选,大幅提升性能:

方案1:dplyr 1.1.0+ 原生非等值连接

library(dplyr)
library(lubridate)

# 先给事件表生成观测窗口终点
event_data_total <- event_data_total %>%
  mutate(event_end_date = event_date %m+% years(2))

# 关联时直接匹配ID和时间区间,无需后续过滤
data_joined_final <- inner_join(
  visit_data,
  event_data_total,
  join_by(
    visit_person_id == event_person_id,
    visit_date >= event_date,
    visit_date <= event_end_date
  )
)

# 若需要每个随访仅保留一条,加去重步骤即可
# data_joined_final <- distinct(data_joined_final, visit_id, .keep_all = TRUE)

方案2:超大数据量用data.table实现

如果随访记录量级达到十万以上,data.table的性能远高于dplyr:

library(data.table)
library(lubridate)

# 转换为data.table格式
setDT(event_data_total)
setDT(visit_data)

# 生成观测窗口终点
event_data_total[, event_end_date := event_date %m+% years(2)]

# 非等值连接,nomatch=NULL等价于inner join
data_joined_final <- event_data_total[visit_data,
  on = .(event_person_id = visit_person_id, event_date <= visit_date, event_end_date >= visit_date),
  nomatch = NULL
]

# 去重(可选)
# data_joined_final <- unique(data_joined_final, by = "visit_id")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:24:04