滚动累积总和以缺失数据为条件

时间:2015-08-18 12:41:26

标签: r data.table cumulative-sum

我想在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行的结果只包括最新的观察结果。

1 个答案:

答案 0 :(得分:3)

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

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

在第二步中,我们同时使用'indx'和'time'作为分组变量,使用rollsum获取'sales'的k=2,并且还基于条件,如果数字组中的元素大于1只有我们需要这样做(if(.N >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的建议,我们可以使用来自roll_sum的{​​{1}}可以更有效地使用,因为它甚至可以使用小于'k'的行数。通过这种方式,我们可以删除先前解决方案中的library(RcppRoll)条件。 (完全归功于@Khashaa)

if/else