按月

2013-10-11 35 views
1

线性分配金额请考虑下面的合成数据帧:按月

#Learning to enable splitting contributions spanning two months 

start = c(as.Date("2013-01-01"), as.Date("2013-02-01"), as.Date("2013-04-01"), as.Date("2013-04-16"), as.Date("2013-05-16")) 
end = c(as.Date("2013-01-31"), as.Date("2013-03-31"), as.Date("2013-04-15"), as.Date("2013-05-15"), as.Date("2013-05-31")) 
amount = c(100, 200, 50, 100, 50) 

df = data.frame(start,end,amount) 

这是收到的现金和它涉及到时间的列表。其中一些时间段为两个月。我想按月汇总。对于那些涉及两个月的期限的数额,我想在两个月之间进行线性分摊/分配。

在R中做这件事的惯用方法是什么?

+0

可能重复的[值的平分配数跨越的时间段(http://stackoverflow.com/questions/18835463/flat-apportionment-of-values-across-time-periods) – Michele

+0

由于米歇尔。我已经阅读了平摊分配问题的答案,并不完全确定如何将其应用于我的示例。我需要更多的指导,因为我对R很陌生,所以还需要一些关于R思维方式中“事情已经完成”的习惯性见解。但是,谢谢你指出! –

+0

在第四行的情况下,你想要的东西分配50美元到四月和50美元可能,或者离开这一个单独的,因为它的总持续时间是一个月? –

回答

4

创建一个函数explode,该函数将间隔分解为一行数据帧,每天有一行。使用Mapexplode应用于每个产生数据帧列表的间隔,每个间隔一个。接下来rbind将列表中的数据帧合并为一个大数据帧,即by.date,每天有一行。最后汇总by.date成一排,每年/月:

library(zoo) # as.yearmon 

explode <- function(start, end, amount) { 
    dates <- seq(start, end, "day") 
    data.frame(dates, yearmon = as.yearmon(dates), amount = amount/length(dates)) 
} 
by.date <- do.call("rbind", Map(explode, df$start, df$end, df$amount)) 
aggregate(amount ~ yearmon, by.date, sum) 

的问题使用数据(假设2010年的发生被认为是2013年),我们得到:

yearmon amount 
1 Jan 2013 100.00000 
2 Feb 2013 94.91525 
3 Mar 2013 105.08475 
4 Apr 2013 100.00000 
5 May 2013 100.00000 

更新:如果内存是一个问题,用它代替explode。它首先在explode内汇总,以使其输出更小。此外,我们已经在DF消除dates列,因为它是只包括用于调试:

explode <- function(start, end, amount) { 
    dates <- seq(start, end, "day") 
    DF <- data.frame(yearmon = as.yearmon(dates), amount = amount/length(dates)) 
    aggregate(amount ~ yearmon, DF, sum) 
} 

更新2:这是另一种尝试。它使用rowsum这是专门用于汇总总和。在我的测试中,这篇文章的数据运行速度提高了10倍。的

explode2 <- function(start, end, amount) { 
    dates <- seq(start, end, "day") 
    n <- length(dates) 
    rowsum(rep(amount, n)/n, format(dates, "%Y-%m")) 
} 
by.date <- do.call("rbind", Map(explode2, df$start, df$end, df$amount)) 
rowsum(by.date, rownames(by.date)) 
+0

我发现这个答案是最清楚的。我没有遇到do.call,但在“花一点时间”之后,我开始明白这一点。这个答案也改善了我对函数式编程的思考,但在我真正掌握链接的扁平分配答案之前,我还有很长的路要走。许多感谢所有。 –