我并不完全不同意使用哪种方法都无所谓,但需要注意它们的行为有所不同。
下面通过一个小例子来举例说明。
这是一些示例数据:
set.seed(1)
mydf <- data.frame(A = c(1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4),
B = LETTERS[c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2)],
matrix(sample(100, 36, replace = TRUE), nrow = 12))
mydf[3:5] <- lapply(mydf[3:5], function(x) {
x[sample(nrow(mydf), 1)] <- NA
x
})
mydf
首先是公式接口。以下三个命令将生成相同的输出。
aggregate(cbind(X1, X2, X3) ~ A + B, mydf, sum)
aggregate(cbind(X1, X2, X3) ~ ., mydf, sum)
aggregate(. ~ A + B, mydf, sum)
以下是 "by" 接口的相关命令。输入时有些繁琐,但如果必要的话可以使用 with
简化。
aggregate(cbind(mydf$X1, mydf$X2, mydf$X3),
by = list(mydf$A, mydf$B), sum)
Group.1 Group.2 V1 V2 V3
1 1 A 123 NA 68
2 2 A 112 122 126
3 3 B 315 311 NA
4 4 B NA 101 169
现在,请停下来并记下任何差异。
我想到的两个差异是:
The formula method does a nicer job of preserving names
but it doesn't let you control the names directly in your command, which you can do in the data.frame
method:
aggregate(cbind(NewX1 = mydf$X1, NewX2 = mydf$X2, NewX3 = mydf$X3),
by = list(NewA = mydf$A, NewB = mydf$B), sum)
The formula method and the data.frame
method treat NA
values differently. To get the same result with the formula method as you do with the data.frame
method, you need to use na.action = na.pass
.
aggregate(. ~ A + B, mydf, sum, na.action=na.pass)
再次强调,“我不认为这真的很重要”并不完全是错误的,而且我也不会在这里表达我的偏好,因为这并不是 Stack Overflow 的主旨,但在做出此类决定之前,仔细阅读函数文档非常重要。
NA
的差异,你提出了一个很好的观点。不幸的是,R
函数在处理NA
方面并不特别一致。 - Carl Witthoftaggregate(mydf[c("X1","X2","X3")], mydf[c("A","B")], sum)
这样的方式大大简化,因为data.frames
是list
s。您还可以在公式界面中重命名,例如aggregate(cbind(NewX1=X1,NewX2=X2,NewX3=X3) ~ cbind(NewA=A) + cbind(NewB=B), data=mydf, sum)
,不用担心。 - thelatemail