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

如何编写循环调整日期时段?合并同ID同剂量的连续治疗周期

问题描述

我有一个包含数千人的大型数据集,每个人的每个治疗周期单独一行记录,字段包括id、inn(开始日期)、out(结束日期)和dose(剂量)。规则是:两个连续治疗周期间隔超过7天的话,会有一行记录该间隔时段且dose=0;间隔小于7天则无此记录。

需求:将每个用户满足以下条件的多个周期合并为一个连续周期:

  • 同一id
  • 同一dose
  • 彼此间隔小于7天
    不同剂量的相邻周期即使间隔小于7天也不合并。

我尝试用ifelse实现,但遇到多个需合并的相邻周期时出错,想写循环又搞不定,求帮助。

示例数据集

library(data.table)

d=data.frame(id=c(1,1,1,1,1,1,1,2,2,2,2,2,2),
             inn=as.Date(c("2017-09-11", "2017-12-21", "2018-03-19", "2018-06-27", "2019-01-15", "2019-04-29", "2019-11-20",
                           "2019-02-06","2019-04-07","2019-05-14","2019-07-13","2019-07-23","2019-09-25")), 
             out=as.Date(c("2017-12-21","2018-03-19", "2018-06-27", "2019-01-15", "2019-04-25", "2019-11-15", "2021-07-10",
                           "2019-04-07","2019-05-14","2019-07-13","2019-07-23","2019-09-21","2021-05-14")),
             dose=c("20","0","20","0", "20", "20","20","2.5","0","2.5","0","2.5","2.5"))

setDT(d)

期望结果

e=data.frame(id=c(1,1,1,1,1,2,2,2,2,2),
             inn=as.Date(c("2017-09-11", "2017-12-21", "2018-03-19", "2018-06-27", "2019-01-15",
                           "2019-02-06","2019-04-07","2019-05-14","2019-07-13","2019-07-23")), 
             out=as.Date(c("2017-12-21","2018-03-19", "2018-06-27", "2019-01-15","2021-07-10",
                           "2019-04-07","2019-05-14","2019-07-13","2019-07-23","2021-05-14")),
             dose=c("20","0","20","0", "20","2.5","0","2.5","0","2.5"))
解决方案

利用data.table的高效分组与窗口函数可以实现需求,无需编写循环,处理大数据集效率更高。核心逻辑是通过标记合并组,再按组聚合得到合并后的周期:

library(data.table)

# 1. 在同id同dose分组内,获取上一个周期的结束日期
d[, prev_out := shift(out), by = .(id, dose)]
# 2. 计算当前周期开始与上一个同剂量周期结束的间隔天数
d[, gap := inn - prev_out]
# 3. 创建合并组标签:间隔≥7天或为组内首条记录时,组号递增
d[, group := cumsum(is.na(gap) | gap >= 7), by = .(id, dose)]
# 4. 按id、dose、group分组,聚合得到合并后的周期(取组内最早inn、最晚out)
result <- d[, .(inn = min(inn), out = max(out)), by = .(id, dose, group)]
# 5. 移除group列并按id、inn排序
result <- result[, !"group"][order(id, inn)]

# 输出结果
print(result)

代码说明

  • shift(out), by = .(id, dose):在同一id和dose的分组内,提取上一行的out日期,用于计算间隔
  • gap := inn - prev_out:得到当前周期与上一个同剂量周期的间隔天数
  • cumsum(is.na(gap) | gap >=7):生成合并组标识,当间隔≥7天或为组内第一条记录(gap为NA)时,组号加1,确保间隔<7天的同剂量周期归为同一组
  • 最后按组聚合,取组内最早的开始日期和最晚的结束日期,得到合并后的连续周期

运行后结果与你给出的期望结果完全一致,且该方法基于向量化操作,处理大规模数据效率优于循环。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:53:19