将事件日期拆分至剧集ID与起始日的矢量化高效实现需求
高效矢量化分组事件至剧集(支持data.table/tibble分组)
我们有一个包含事件日期的数据集,每个事件归属未知剧集,需按以下规则完成分组:
- 同一剧集内所有事件与该剧集起始日的间隔不超过180天
- 每个事件需标记对应剧集的起始日
- 需支持百万级独立患者的批量计算,优先采用矢量化方案,可在data.table的
by或分组tibble中运行,拒绝低效的循环类实现
示例输入输出
输入事件日期向量
event_dates <- c(34, 102, 190, 202, 245, 460, 500, 517)
期望输出
- 剧集ID向量:
c(1, 1, 1, 1, 2, 3, 3, 3)
- 剧集起始日向量:
c(34, 34, 34, 34, 245, 460, 460, 460)
分组逻辑说明
- 第5条记录(日期245)与第一剧集起始日34间隔超过180天,开启新剧集
- 第6条记录(日期460)与第二剧集起始日245间隔超过180天,开启新剧集,以此类推
矢量化实现方案
1. data.table 版本(适配大数据场景)
利用data.table的分组能力和累积计算函数,全程矢量化处理:
library(data.table) # 构造模拟数据(含患者ID,模拟百万级患者场景) dt <- data.table( patient_id = rep(1:2, each = 8), event_dates = c(34, 102, 190, 202, 245, 460, 500, 517, 10, 50, 200, 220, 300, 500, 550, 600) ) # 按患者分组计算剧集ID和起始日 dt[, `:=`( episode_start = { # 标记新剧集起始点:第一条事件,或当前事件与上一剧集起始日间隔>180天 new_episode = c(TRUE, event_dates[-1] > cummax(event_dates)[-1] - 180) # 用cummax保留当前剧集的起始日 cummax(ifelse(new_episode, event_dates, 0)) }, episode_id = { # 对新剧集起始点累积计数生成剧集ID cumsum(c(TRUE, event_dates[-1] > cummax(event_dates)[-1] - 180)) } ), by = patient_id] # 查看处理结果 print(dt)
2. dplyr(分组tibble)版本
利用dplyr窗口函数实现矢量化分组:
library(dplyr) # 构造模拟数据 df <- tibble( patient_id = rep(1:2, each = 8), event_dates = c(34, 102, 190, 202, 245, 460, 500, 517, 10, 50, 200, 220, 300, 500, 550, 600) ) # 按患者分组计算 df_processed <- df %>% group_by(patient_id) %>% mutate( # 标记新剧集起始点 new_episode = c(TRUE, event_dates[-1] > cummax(event_dates)[-1] - 180), # 生成剧集ID episode_id = cumsum(new_episode), # 标记剧集起始日 episode_start = cummax(ifelse(new_episode, event_dates, 0)) ) %>% ungroup() # 查看处理结果 print(df_processed)
方案说明
- 核心逻辑:通过
cummax跟踪当前剧集的起始日,判断后续事件是否超出180天阈值,标记新剧集后用cumsum生成剧集ID,全程无循环,计算效率远高于逐行判断的方案 - 两种方案均支持按患者分组批量处理,可直接适配百万级患者的数据集
内容的提问来源于stack exchange,提问作者Noah
相关产品推荐
相关产品推荐

