Другая опция, использующая tapply
:
dat <- data.frame(key = c('a', 'b', 'a'), val = c(5,7,6))
> with(dat, tapply(val, key, FUN = sum))
a b
11 7
Мои тесты показывают, что это самый быстрый метод для этого конкретного упражнения, очевидно, ваши мили могут отличаться:
fn.tapply <- function(daters) with(daters, tapply(val, key, FUN = sum))
fn.aggregate <- function(daters) aggregate(val~key, sum, data = daters)
fn.ddply <- function(daters) ddply(daters, .(key), summarize, val = sum(val))
library(rbenchmark)
benchmark(fn.tapply(dat), fn.aggregate(dat), fn.ddply(dat)
, columns = c("test", "elapsed", "relative")
, order = "relative"
, replications = 100
)
test elapsed relative
1 fn.tapply(dat) 0.03 1.000000
2 fn.aggregate(dat) 0.20 6.666667
3 fn.ddply(dat) 0.30 10.000000
Обратите внимание, что преобразование решения tapply
в data.frame сократило эту разницу наполовину на ~ 40% для сравнения истинных яблок с яблоками по сравнению с первыми двумя.
Использование набора данных строки 1M, как указано в комментариях, кажется, немного меняет положение:
dat2 <- data.frame(key = rep(letters[1:5], each = 200000), val = runif(1e6))
> benchmark(fn.tapply(dat2), fn.aggregate(dat2), fn.ddply(dat2)
+ , columns = c("test", "elapsed", "relative")
+ , order = "relative"
+ , replications = 100
+ )
test elapsed relative
1 fn.tapply(dat2) 39.114 1.000000
3 fn.ddply(dat2) 62.178 1.589661
2 fn.aggregate(dat2) 157.463 4.025745