我正在尝试创建一个函数,在按 id、start_ins、rxdate 排序的数据中考虑重叠周期:
dt <- data.table(
id = c(1, 2, 2, 3,3,3),
start_ins = as.Date(c('2000-10-12', '2000-03-31', '2000-03-31', '2000-01-11', '2000-01-11', '2000-01-11')),
rxdate = as.Date(c('2010-01-04', '2010-03-30', '2010-04-08', '2003-12-29', '2004-01-12' , '2004-03-10')),
amount = c(30, 28, 100, 60, 1, 10),
rx_end = as.Date(c('2010-02-03', '2010-04-27', '2010-07-17', '2004-02-27', '2004-01-13', '2004-03-20'
)
在此集合中,观测值按 id 和 start_ins 分组。人们还会根据日期和药片数量(数量)购买处方药。 rx_end 是
[, rx_end := rxdate + amount]
但是,如果仔细观察,您会发现第 2 行的 rx_end 位于第 3 行的 rxdate 之后。在这种情况下,第 3 行的 rxdate 和上一个处方的末尾之间存在重叠。我想假设一个人在开始新的治疗之前完成了一次治疗。在这种情况下,第 3 行的 rxdate 应在第 2 行的 rx_end 之后的一天开始,并且第 3 行的 rx_end 应更新,以考虑第 3 行中的新 rxdate。相同的逻辑适用于第 4 行和第 5 行。在这种情况下,新的 rxdate数据集看起来像这样:
dt1 <- data.table(
id = c(1, 2, 2, 3, 3, 3),
start_ins = as.Date(c('2000-10-12', '2000-03-31', '2000-03-31', '2000-01-11', '2000-01-11', '2000-01-11')),
rxdate = as.Date(c('2010-01-04', '2010-03-30', '2010-04-28', '2003-12-29', '2004-02-28', '2004-03-10')),
amount = c(30, 28, 100, 60, 1, 10),
rx_end = as.Date(c('2010-02-03', '2010-04-27', '2010-08-06', '2004-02-27', '2004-02-29', '2004-03-20'
).
我尝试使用 data.table 编写这个函数:
overlapper <- function (dt){
dt[,{
prev_end_date <- shift(rx_end, 1, type = "lag")
for (i in 2:.N){
if(!is.na(prev_end_date[i-1]) & prev_end_date >= dt[i, rxdate]){
dt[i, rxdate := prev_end_date[i-1] +1]
dt[i, rx_end := rxdate + amount]
}
prev_end_date[i] <- dt[i, rx_end]
}
return(dt)}, by = .(id, start_ins)]}
请记住,有些人只有一个观察结果,因此不应考虑这些,这就是为什么我要按 id 和 start_ins 进行分组操作。 我总是想查看第 n 行并将其与 n-1 进行比较,以仅在存在重叠时更新第 n 行。如果没有重叠,我会保持这条线不变,然后继续下一条线。
您可以使用
data.table::shift()
来完成此操作:
dt[, rx_days := rx_end - rxdate][
, rxdate := fifelse(
rxdate < shift(rx_end, 1, fill = rxdate[1]),
shift(rx_end, 1) + 1,
rxdate
),
id
][, rx_end := rxdate + rx_days][,
rx_days := NULL
]
dt
# id start_ins rxdate amount rx_end
# <num> <Date> <Date> <num> <Date>
# 1: 1 2000-10-12 2010-01-04 30 2010-02-03
# 2: 2 2000-03-31 2010-03-30 28 2010-04-27
# 3: 2 2000-03-31 2010-04-28 100 2010-08-06
# 4: 3 2000-01-11 2003-12-29 60 2004-02-27
# 5: 3 2000-01-11 2004-02-28 1 2004-02-29
# 6: 3 2000-01-11 2004-03-10 10 2004-03-20
identical(dt, dt1)
# [1] TRUE