【发布时间】:2021-05-04 01:15:30
【问题描述】:
我有一个表,其中包含特定时间间隔内存在的值。我想要一个字段来汇总在该时间间隔的开始时间内存在的给定 ID 的所有值。
这是一个配对的例子:
x = data.table(ID = c(rep(1, 5), rep(2, 5)),
DT_START = as.Date(c('2017-05-28', '2017-05-29', '2017-07-03', '2018-05-28', '2018-05-29',
'2019-07-03', '2019-10-08', '2020-05-28', '2020-05-29', '2020-07-03')),
DT_END = as.Date(c('2018-05-28', '2018-05-29', '2018-07-03', '2018-05-29', '2019-05-28',
'2019-10-08', '2020-07-03', '2021-05-28', '2021-05-29', '2020-10-03')),
VALUE = c(300, 400, 200, 100, 150, 250, 350, 50, 10, 45))
表格如下所示:
x
ID DT_START DT_END VALUE
1: 1 2017-05-28 2018-05-28 300
2: 1 2017-05-29 2018-05-29 400
3: 1 2017-07-03 2018-07-03 200
4: 1 2018-05-28 2018-05-29 100
5: 1 2018-05-29 2019-05-28 150
6: 2 2019-07-03 2019-10-08 250
7: 2 2019-10-08 2020-07-03 350
8: 2 2020-05-28 2021-05-28 50
9: 2 2020-05-29 2021-05-29 10
10: 2 2020-07-03 2020-10-03 45
在第一行中,这是该 ID 的第一个开始日期,并且没有相等的日期,因此累积值将只有 300。到第二行,我们现在添加 300+400 得到 700,因为如2017 年 5 月 29 日,ID 1 的 400 和 300 都处于活动状态。使用以下代码获得完整的所需输出向量:
x[, VALUE_CUM := sum(x$VALUE * ifelse(x$ID == ID & x$DT_START <= DT_START & x$DT_END > DT_START, 1, 0)), by = .(ID, DT_START)]
x
ID DT_START DT_END VALUE VALUE_CUM
1: 1 2017-05-28 2018-05-28 300 300
2: 1 2017-05-29 2018-05-29 400 700
3: 1 2017-07-03 2018-07-03 200 900
4: 1 2018-05-28 2018-05-29 100 700
5: 1 2018-05-29 2019-05-28 150 350
6: 2 2019-07-03 2019-10-08 250 250
7: 2 2019-10-08 2020-07-03 350 350
8: 2 2020-05-28 2021-05-28 50 400
9: 2 2020-05-29 2021-05-29 10 410
10: 2 2020-07-03 2020-10-03 45 105
这很棒,但在我拥有数百万行的庞大数据表上需要很长时间。有关如何更优雅地执行此操作以加快速度的任何想法?
谢谢!
【问题讨论】:
-
你可以对 self 使用非相等连接
-
如何理解第 4 行的
VALUE_CUM = 700? -
700 是 400 + 200 + 100 的总和。前 300 个不再计算在内,因为它在 2018 年 5 月 28 日之前不再处于活动状态(这是 700 行的开始日期)。
标签: r data.table