【问题标题】:R data.table cumulative sum over time intervalsR data.table 时间间隔内的累积总和
【发布时间】: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


【解决方案1】:

这是一种可能的方法:

y <- x[x, .(
    DT_END2 = i.DT_END,
    VALUE = i.VALUE, VALUE_CUM = sum(x.VALUE)),
    on = .(ID, DT_START <= DT_START, DT_END > DT_START), by = .EACHI]

# DT_END is overwritten by values of DT_START, so we use DT_END2 to backup the correct DT_END values.
y[, DT_END := DT_END2][, DT_END2 := NULL]

#     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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 2020-08-27
    • 2016-02-19
    • 2014-07-13
    • 1970-01-01
    • 2013-08-23
    相关资源
    最近更新 更多