OP 有requested:
从每个组中的第一次观察 X 开始,我想标记距离 X 不到 90 天的任何其他观察。然后对于距离 X 大于 90 天的第二天观察,称之为观察 Y,我想标记 Y 后 90 天内的任何观察结果。重复。
如果我从预期结果中正确理解,with.90d 列中的值FALSE 表示 90 天期间的开始。
很遗憾,下一个 90 天期限的开始时间取决于前一个 90 天期限到期后的下一次观察日期。因此,我们不能使用从每个组的第一个日期开始的固定 90 天间隔。
我曾尝试使用 non-equi joins 或 rolling joins 找到解决方案,但到目前为止我最终还是采用了递归方法:
dt3[, with.90d := NA]
while (dt3[, any(is.na(with.90d))])
dt3[is.na(with.90d), cd := date - min(date), by = id][
is.na(with.90d) & cd == 0, with.90d := FALSE][
is.na(with.90d) & cd <= 90, with.90d := TRUE]
dt3
id date with.90d cd
1: A 2017-01-01 FALSE 0 days
2: A 2017-02-01 TRUE 31 days
3: A 2017-05-01 FALSE 0 days
4: B 2017-01-01 FALSE 0 days
5: B 2017-05-01 FALSE 0 days
6: B 2017-10-01 FALSE 0 days
7: C 2017-01-01 FALSE 0 days
8: C 2017-02-01 TRUE 31 days
9: C 2017-02-15 TRUE 45 days
10: D 2017-03-01 FALSE 0 days
11: D 2017-04-01 TRUE 31 days
12: D 2017-05-01 TRUE 61 days
13: D 2017-06-01 FALSE 0 days
14: D 2017-07-01 TRUE 30 days
15: D 2017-08-01 TRUE 61 days
16: E 2017-01-01 FALSE 0 days
17: E 2017-02-01 TRUE 31 days
18: E 2017-03-01 TRUE 59 days
19: E 2017-04-01 TRUE 90 days
20: E 2017-05-01 FALSE 0 days
21: E 2017-06-01 TRUE 31 days
id date with.90d cd
请注意,我在 OP 的示例数据集中添加了另外两个组 D 和 E,以便更好地验证该方法。还要注意从2017-03-01 开始的D 组和从2017-01-01 开始的E 组的结果有何不同。
说明
只要with.90d 中有NA 值,就重复以下顺序仅针对NA 行(具有TRUE 或FALSE 值的行已完成) :
- 计算每组中第一个日期的天差。请注意,使用了
min(date),它也适用于无序数据集。或者,可以使用setorder(dt3, date) 和first(date)(或date[1])。
- 日差为
0 的行表示新周期的开始,并标记为FALSE。
- 日差小于或等于 90 天的行被标记为
TRUE。
- 所有其他行保持不变,即它们保持
NA 值。
为了说明,我保留了帮助器列cd。可以通过dt3[, cd := NULL]删除。
数据
# OP's sample dataset
dt <- data.table(id = c("A", "A", "A", "B", "B", "B", "C", "C", "C"),
date = as.Date(c("2017-01-01", "2017-02-01", "2017-05-01", "2017-01-01", "2017-05-01", "2017-10-01", "2017-01-01", "2017-02-01", "2017-02-15")))
# append group D
dt2 <- dt[, .(id = c(id, rep("D", 6)),
date = c(date, seq(as.Date("2017-03-01"), length.out = 6, by = "1 month")))]
# append group E
dt3 <- dt2[, .(id = c(id, rep("E", 6)),
date = c(date, seq(as.Date("2017-01-01"), length.out = 6, by = "1 month")))]