假设我们有以下内容:
time=c(20060200,20060200,20060200,20060200,20060200,20060300,20060400,20060400,20060400)
bucket=c(1,1,2,2,1,3,3,3,1)
rate=c(0.05,0.04,0.04,0.05,0.06,0.01,0.07,0.08,0.03)
time bucket rate
1: 20060200 1 0.05
2: 20060200 1 0.04
3: 20060200 2 0.04
4: 20060200 2 0.05
5: 20060200 1 0.06
6: 20060300 3 0.01
7: 20060400 3 0.07
8: 20060400 3 0.08
9: 20060400 1 0.03
我知道如何通过类似的方式将费率汇总到时间或桶中
test=data.table(time,bucket,rate)
b=test[,list(x=sum(rate)),by=bucket]
我的问题是如何聚合到桶中,同时保持时间不变 所以我想要的是这样的:
20060200 1 0.15
20060200 2 0.09
20060200 3 0
20060300 1 0
20060300 2 0
20060300 3 0.01
20060400 1 0.03
20060400 2 0
20060400 3 0.15
希望这很清楚,谢谢
答案 0 :(得分:5)
正如@Mittenchops所说,你正在寻找笛卡尔积。有一个功能,CJ
。您可以使用unique(CJ(time,bucket))
获得所需的组合。要在data.table中使用它,您可以(i)设置密钥并(ii)将其与CJ一起加入:
setkey(test,time,bucket)
b <- test[unique(CJ(time,bucket)),list(x=sum(rate))]
b[is.na(x),x:=0]
最后一步将缺失值设置为0.结果是:
time bucket x
1: 20060200 1 0.15
2: 20060200 2 0.09
3: 20060200 3 0.00
4: 20060300 1 0.00
5: 20060300 2 0.00
6: 20060300 3 0.01
7: 20060400 1 0.03
8: 20060400 2 0.00
9: 20060400 3 0.15
顺便说一句,当你使用x[y,...]
语法“加入”时(其中x和y都是data.tables),有一个隐藏的by
... a by-without-by。 ..在(可能只是第一部分)x的键上。在文档或谷歌上查找“by-without-by”以获取详细信息。
答案 1 :(得分:0)
听起来让你的问题变得困难的事情就是聚合更少,更多的是关于按群体创建时间的笛卡尔积,以填补聚合所留下的空白。如果函数中有一个标志来实现这一点会很棒,但似乎没有。
所以,这不是很优雅,但是这里有一个解决方案,通过构建该结构,然后将聚合结果移植到该脚手架上来实现这一点:
df <- aggregate(rate~., data=test, sum)
> df
time bucket rate
1 20060200 1 0.15
2 20060400 1 0.03
3 20060200 2 0.09
4 20060300 3 0.01
5 20060400 3 0.15
弄清楚我们需要创建笛卡尔脚手架的水平,在这种情况下,所有群体都要创建:
> levels(factor(bucket))
[1] "1" "2" "3"
> levels(factor(time))
[1] "20060200" "20060300" "20060400"
> B <- levels(factor(bucket))
> t <- levels(factor(time))
制作一个格子基底以将结果移植到:
> base <- expand.grid(B,t)
> names(base) <-c("bucket","time")
> base
bucket time
1 1 20060200
2 2 20060200
3 3 20060200
4 1 20060300
5 2 20060300
6 3 20060300
7 1 20060400
8 2 20060400
9 3 20060400
将数据框合并到基础上:
> m <- merge(base,df,all.x=T)
bucket time rate
1 1 20060200 0.15
2 1 20060300 NA
3 1 20060400 0.03
4 2 20060200 0.09
5 2 20060300 NA
6 2 20060400 NA
7 3 20060200 NA
8 3 20060300 0.01
9 3 20060400 0.15
将NA替换为0:
m$rate[is.na(m$rate)] <- 0
> m
bucket time rate
1 1 20060200 0.15
2 1 20060300 0.00
3 1 20060400 0.03
4 2 20060200 0.09
5 2 20060300 0.00
6 2 20060400 0.00
7 3 20060200 0.00
8 3 20060300 0.01
9 3 20060400 0.15
排序以获得所需的输出:
> m[with(m,order(time,bucket)),]
bucket time rate
1 1 20060200 0.15
4 2 20060200 0.09
7 3 20060200 0.00
2 1 20060300 0.00
5 2 20060300 0.00
8 3 20060300 0.01
3 1 20060400 0.03
6 2 20060400 0.00
9 3 20060400 0.15