1)骨料對於問題的具體例子一個通常會使用在基礎R aggregate
而非by
:
aggregate(mpg ~ vs + am, mtcars, function(x) c(length = length(x), mean = mean(x)))
給出:
vs am mpg.length mpg.mean
1 0 0 12.00000 15.05000
2 1 0 7.00000 20.74286
3 0 1 6.00000 19.75000
4 1 1 7.00000 28.37143
2)通過如果實際問題更復雜,而且您確實需要使用by
,則格式化by
對象,因爲by
語句應該重寫爲在整個數據框上運行幷包含邊距變量在功能:
fun <- function(x) with(x,
data.frame(vs = vs[1], am = am[1], length = length(mpg), mean = mean(mpg)))
do.call("rbind", by(mtcars, mtcars[c("vs", "am")], fun))
給予:
vs am length mean
1 0 0 12 15.05000
2 1 0 7 20.74286
3 0 1 6 19.75000
4 1 1 7 28.37143
3)通過使用從問題 b儘管這不是recommmended將有可能噸o在問題中改革b
。我們稍微重申了b
使用更簡潔的符號和添加名稱。在意識到"by"
對象b
也正是在這種情況下,一個2x2矩陣,我們可以將其轉換成數據幀,調換它給矩陣m
,得到b
的行名的利潤給margins
和cbind
一切融合在一起:
b <- by(mtcars$mpg, mtcars[c("vs", "am")], function(x) c(length=length(x), mean=mean(x)))
m <- t(do.call("data.frame", c(as.data.frame.matrix(b), check.names = FALSE)))
margins <- read.table(text = rownames(m), sep = ".", col.names = rev(names(dimnames(b))))
cbind(margins, m)
給予:
am vs length mean
0.0 0 0 12 15.05000
0.1 0 1 7 20.74286
1.0 1 0 6 19.75000
1.1 1 1 7 28.37143
4)sqldf它也將是可能的解決使用任何許多包例如data.table,doBy,dplyr和sqldf的這個特定問題。在這裏,我們表現出sqldf解決方案:
library(sqldf)
sqldf("select vs, am, count(*) length, avg(mpg) mean
from mtcars
group by vs, am")
,並提供:
vs am length mean
1 0 0 12 15.05000
2 0 1 6 19.75000
3 1 0 7 20.74286
4 1 1 7 28.37143
請用'dplyr'代替? – Gregor
@Gregor實際上,我自己使用'ddply',但感謝您的建議。我一直想學習'dplyr'一段時間,這又增加了另一個原因。 – Empiromancer