我想知道如何确保在使用聚合时我包含所有因素的相互作用,即使它们不会出现在给定的数据集中。
dff <- data.frame(a=as.factor(c(rep(1,3), rep(2,4), rep(3,3))),
b=as.factor(c(rep("A", 4), rep("B",6))),
c=sample(100,10))
levels(dff$b) <- c(levels(dff$b), "C")
levels(dff$a) <- c(levels(dff$a), 10)
dff$b
#[1] A A A A B B B B B B
#Levels: A B C
dff$a
#[1] 1 1 1 2 2 2 2 3 3 3
#Levels: 1 2 3 10
aggregate(c~a+b, dff, sum)
# a b c
#1 1 A 233
#2 2 A 78
#3 2 B 212
#4 3 B 73
我想要的是
a b c
1 1 A 233
2 1 B 0
3 1 C 0
4 2 A 78
5 2 B 212
6 2 C 0
7 3 A 0
8 3 B 73
9 3 C 0
10 10 A 0
11 10 B 0
12 10 C 0
NA也很好。
我想要这种格式的原因是因为我需要将dff $ c与来自其他数据集的结果进行交互,如果不考虑所有因子水平,它们可能具有不同的长度。我尝试避免合并,而是使用矢量计算。
提前谢谢你。
答案 0 :(得分:2)
如果您的聚合函数只是sum
,您可以使用xtabs
,这将创建一个包含类table
的对象。因此,您可以使用data.frame
,它会调用相应的“方法”,从而创建“长”data.frame
。
data.frame(xtabs(c ~ b + a, dff))
# b a Freq
# 1 A 1 121
# 2 B 1 0
# 3 C 1 0
# 4 A 2 89
# 5 B 2 203
# 6 C 2 0
# 7 A 3 0
# 8 B 3 126
# 9 C 3 0
# 10 A 10 0
# 11 B 10 0
# 12 C 10 0
这类似于@ nicola建议使用as.data.frame.table
,它明确地将该方法调用为非明确属于类“table”但可被视为一个的东西。
此方法(以及随后的所有其他方法)的一个优点是您可以使用sum
以外的其他功能。
as.data.frame.table(tapply(dff$c, dff[c("a","b")], sum))
如果merge
没问题,您可以继续执行aggregate
步骤。在这种情况下,我们会在您的因子向量expand.grid
上使用levels
:
merge(expand.grid(lapply(dff[c(1, 2)], levels)),
aggregate(c~a+b, dff, sum, drop = FALSE), all = TRUE)
可以在“data.table”中采用类似的方法:
library(data.table)
as.data.table(dff)[, sum(c), by = .(a, b)][do.call(CJ, lapply(dff[c(1, 2)], levels)), on = c("a", "b")]
或使用“dplyr”+“tidyr”(基本上隐藏了合并,但最终使用left_join
来创建缺少的组合):
library(dplyr)
library(tidyr)
dff %>%
group_by(a, b) %>%
summarise(c = sum(c)) %>%
complete(a, b, fill = list(c = 0))