【问题标题】:rolling cumulative sums conditional on missing data以缺失数据为条件的滚动累积总和
【发布时间】:2015-08-18 12:41:25
【问题描述】:

我想在 data.table 中按项目计算滚动累积总和。有时,给定时间段内的数据会丢失。

set.seed(8)
item <- c(rep("A",4), rep("B",3))
time <- c(1,2,3,4,1,3,4)
sales <- rpois(7,5)
DT <-  data.table(item, time,sales)

对于 2 个时间段的滚动窗口,我想要以下输出:

   item time sales sales_rolling2
1:    A    1     5              5
2:    A    2     3              8
3:    A    3     7             10
4:    A    4     6             13
5:    B    1     4              4
6:    B    3     6              6
7:    B    4     4             10

注意,项目 B 在时间 2 没有数据。因此,第 6 行的结果只包括最新的观察结果。

【问题讨论】:

    标签: r data.table cumulative-sum


    【解决方案1】:

    我们可以使用library(zoo) 中的rollsum 进行滚动求和。在应用rollsum 之前,我想我们需要根据'time' 变量创建另一个分组变量('indx')。我发现对于项目'B',时间不是连续的,即。 2 不见了。所以,我们可以使用diff来根据相邻元素的差异创建一个逻辑索引。如果差值不为 1,则返回 TRUE,否则返回 FALSE。由于diff 的输出比列的length 小1,所以我们可以用TRUE 填充,然后执行cumsum 来创建'indx' 变量。

    library(zoo)
    DT[, indx:=cumsum(c(TRUE, diff(time)!=1))]
    

    第二步,我们同时使用'indx'和'time'作为分组变量,得到'sales'的rollsumk=2,并且还基于条件,如果在group 大于 1 只有我们需要这样做(if(.N &gt;1)),否则它应该返回“sales”,创建“sales_rolling2”,并将“indx”分配(:=)为 NULL,因为它不需要在预期的输出中。

    DT[, sales_rolling2 := if(.N>1) c(sales[1],rollsum(sales,2)) else sales,
                   by = .(indx, item)][,indx:= NULL]
    #   item time sales sales_rolling2
    #1:    A    1     5              5
    #2:    A    2     3              8
    #3:    A    3     7             10
    #4:    A    4     6             13
    #5:    B    1     4              4
    #6:    B    3     6              6
    #7:    B    4     4             10
    

    更新

    根据@Khashaa 的建议,我们可以更有效地使用library(RcppRoll) 中的roll_sum,因为它甚至可以处理小于“k”的行数。这样,我们就可以去掉我之前解决方案中的if/else条件。 (完全归功于@Khashaa)

    library(RcppRoll)
    DT[, sales_rolling2 := c(sales[1L], roll_sum(sales, 2)), by = .(indx, item)]
    

    【讨论】:

    • 这行得通,但我如何将它扩展到更宽的窗口?例如,3 个时间段的滚动窗口。
    • @lever 只需更改k 值,即k=3
    • @lever 我猜这是由于行数少于 3。所以代替 if(.N&gt;1) ,可能你可以使用 if(.N&gt;3) 左右。
    • @akrun RcppRoll 在行数小于窗口大小时有效(即返回NA)。
    • @akrun RcppRoll::roll_sum 代替 zoo::rollsum
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-29
    相关资源
    最近更新 更多