【发布时间】:2011-11-04 15:05:26
【问题描述】:
我有以下匹配问题:我有两个 data.frame,一个每个月都有一次观察(每个公司 ID),一个每个季度都有一个观察(每个公司 ID;请注意,季度表示财政季度;因此 1Q = 一月、二月、三月不一定正确,一个财政季度也不一定是 3 个月)。
对于每个月和每个公司,我都想获得该季度的正确值。因此,对于一个季度,几个月的值相同。作为示例,请参见下面的代码:
monthlyData <- data.frame(ID = rep(c("A", "B"), each = 5),
Month = rep(1:5, times = 2),
MonValue = 1:10)
monthlyData
ID Month MonValue
1 A 1 1
2 A 2 2
3 A 3 3
4 A 4 4
5 A 5 5
6 B 1 6
7 B 2 7
8 B 3 8
9 B 4 9
10 B 5 10
#Quarterly data, i.e. the value of every quarter has to be matched to several months in d1
#However, I want to match fiscal quarters, which means that one quarter is not necessarily 3 month long
qtrData <- data.frame(ID = rep(c("A", "B"), each = 2),
startMonth = c(1, 4, 1, 3),
endMonth = c(3, 5, 2, 5),
QTRValue = 1:4)
qtrData
ID startMonth endMonth QTRValue
1 A 1 3 1
2 A 4 5 2
3 B 1 2 3
4 B 3 5 4
#Desired output
ID Month MonValue QTRValue
1 A 1 1 1
2 A 2 2 1
3 A 3 3 1
4 A 4 4 2
5 A 5 5 2
6 B 1 6 3
7 B 2 7 3
8 B 3 8 4
9 B 4 9 4
10 B 5 10 4
注意:这个问题是几个月前在 R-help 上发布的,但当时我没有得到任何答案,我自己找到了解决方案(参见 R-help)。然而,现在,我在 stackoverflow 上发布了一个问题,其中我有一个关于 data.table 的问题,其中也提到了这个问题,Andrie 让我再次发布这个问题,因为他显然有一个很好的解决方案(见 @ 987654322@)
更新:见 Matthew Dowle 的评论:真实数据看起来如何?
这个数据是比较真实的。我添加了几行,但唯一改变的主要部分是qtrData 中的列endMonth。更准确地说,startMonth 不一定是上一季度的endMonth 加上一个月。因此,使用roll 选项,我认为您需要另一行代码(如果不需要,您将获得 20 行,但使用 Andrie 的解决方案,这是所需的解决方案,您将获得 17 行)。如果我在这里没有遗漏任何东西,那么就没有性能差异了。
monthlyData_new <- data.table(ID = rep(c("A", "B"), each = 10),
Month = rep(1:10, times = 2),
MonValue = 1:20)
qtrData_new <- data.table(ID = rep(c("A", "B"), each = 3),
startMonth = c(1, 4, 7, 1, 3, 8),
endMonth = c(3, 5, 10, 2, 5, 10),
QTRValue = 1:6)
setkey(qtrData_new, ID)
setkey(monthlyData_new, ID)
qtrData1 <- qtrData_new
setkey(qtrData1, ID, startMonth)
monthlyData1 <- monthlyData_new
setkey(monthlyData1, ID, Month)
withTable1 <- function(){
xx <- qtrData1[monthlyData1, roll=TRUE]
xx <- xx[startMonth <= endMonth]
}
withTable2 <- function(){
yy <- monthlyData_new[qtrData_new][Month >= startMonth & Month <= endMonth]
}
benchmark(withTable1, withTable2, replications=1e6)
test replications elapsed relative user.self sys.self user.child sys.child
1 withTable1 1000000 4.244 1.028599 4.232 0.008 0 0
2 withTable2 1000000 4.126 1.000000 4.096 0.028 0 0
【问题讨论】:
-
我从来没有说过我有一个好的解决方案。你应该自己判断:-)
-
我对你说实话,@Andrie,这不是一个好解决方案......这是一个很棒的解决方案!
-
@Andrie 就在基准(来自 Andrie)上,它重复了一个非常小的操作 100 万次。所有这些时间都是大量的呼叫开销。您需要构建一个 large 表并比较每个方法的 single 运行时间(通常是 3 次运行中最低的一次)。
-
@MatthewDowle 好的,感谢您的关注。我会相应地调整我的代码。
标签: r data.table