【发布时间】:2018-02-15 03:21:31
【问题描述】:
我的问题受到Cumulative sum in a window (or running window sum) based on a condition in R 的启发。
我想计算运行窗口总和,就像上面的帖子一样,有点扭曲。即使没有满足过滤条件的行,我也想将累积总和的值“结转”到“k”年。换句话说,我们需要向原始数据集添加行。
这个问题很有挑战性,因为我仍然不习惯在 data.table 中使用 apply 函数。
这是我的输入数据:
DFI <- structure(list(Year = c(2011, 2013, 2014, 2010, 2012, 2015),
Customer = c(13575, 13575, 13575, 13575, 13576, 13576), Product = c("R",
"R", "R", "W", "S", "R"), Rev = c(4, 1, 2, 1, 2, 2)), .Names = c("Year",
"Customer", "Product", "Rev"), row.names = c(NA, -6L), class = "data.frame")
这是我的预期输出:
DFO <- structure(list(Year = c(2011, 2012, 2013, 2014, 2015, 2010, 2011,
2015, 2012, 2013), Customer = c(13575, 13575, 13575, 13575, 13575,
13575, 13575, 13576, 13576, 13576), Product = c("R", "R", "R",
"R", "R", "W", "W", "R", "S", "S"), Rev = c(4, 0, 1, 2, 0, 1,
0, 2, 2, 0), CumRev = c(4, 4, 1, 3, 2, 1, 1, 2, 2, 2)), .Names = c("Year",
"Customer", "Product", "Rev", "CumRev"), class = "data.frame", row.names = c(NA,
-10L))
关于我如何手动生成DFO的一些评论:
a) 窗口中的年数 = 2 即k=2
b) 虽然Year = 2012、Customer = 13575 和Product = R 的条目在DFI(输入数据)中不存在,但添加它是因为来自Year = 2011 的累积总和将结转1更多年(即k-1 = 2-1 = 1)。因此,对于这一行,Rev = 0 和 CumRev = 4
c) The entry for Year = 2015、Customer = 13575 和 Product = R 已添加,因为表中至少存在一个 Year = 2015 条目。换言之,Year 的范围要添加(或结转)取决于两件事:1)输入表中Year 的范围 2)运行窗口的长度。
现在,我确实在发布之前尝试自己解决了这个问题。我花了将近 36 个小时,我能够解决这个问题。但是,问题在于expand.grid. 在实际数据中,我的内存不足。因此,我想知道是否有更好的方法(计算成本更低且内存效率更高)来解决这个问题。
这是我的代码:
Year<-unique(DFI$Year)
Customer<-unique(DFI$Customer)
Product<-unique(DFI$Product)
DFO1<-expand.grid(Year = Year,Customer = Customer,Product = Product) #generate all combinations
DFO1<-data.table::as.data.table(DFO1)
#Do join between DFO and DFI to add Rev
DFO1<-DFI[DFO1,on=c("Product","Customer","Year")]
k<-2 #Number of years = 2
DFO1<-DFO1[order(Customer,Product,Year)]
DFO1[is.na(Rev)]$Rev<-0
DFO1<-DFO1[, CumRev := sapply(Year, function(year) sum(Rev[between(Year, year-k+1, year)])), by = .(Customer, Product)][order(Customer,Product,Year)]
DFO1<-DFO1[CumRev!=0] #Remove zero rows
DFO<-data.table::as.data.table(DFO)
DFO<-DFO[order(Customer,Product,Year)]
compare(DFO1,DFO) #TRUE
作为一个刚刚开始学习在data.table 中应用apply() 的人,这对我来说很难。我很感激任何优化这个的想法。我愿意从这个过程中学习。感谢您抽出宝贵时间以及对我的任何帮助。
【问题讨论】:
-
DFO中的完整组合不存在吗? -
@akrun - 是的。我删除了它们(使用
DFO1<-DFO1[CumRev!=0]),因为我们只需要结转k-1年的累积总和。 -
为什么没有 Year=2016, Customer=13576, Product=R 的条目?
-
@Chinsoon:感谢您的提问。有两个标准可以确定将添加哪些行
max(year)和k-1。请参见上面的 c) 点。如果我们有任何一个条目,例如,2016年的任何其他客户,我们将需要它。因为year = 2016没有条目,所以我们通过了。简单来说就是current year = 2015
标签: r dplyr data.table