Вместо обычного фрейма данных R вы можете использовать неизменяемый фрейм данных, который возвращает указатели на оригинал, когда вы вводите подмножество, и может быть намного быстрее:
idf <- idata.frame(myDF)
system.time(aggregateDF <- ddply(idf, c("year", "state", "group1", "group2"),
function(df) wtd.mean(df$myFact, weights=df$weights)))
# user system elapsed
# 18.032 0.416 19.250
Если бы я писал функцию plyrНастроенный именно для этой ситуации, я бы сделал что-то вроде этого:
system.time({
ids <- id(myDF[c("year", "state", "group1", "group2")], drop = TRUE)
data <- as.matrix(myDF[c("myFact", "weights")])
indices <- plyr:::split_indices(seq_len(nrow(data)), ids, n = attr(ids, "n"))
fun <- function(rows) {
weighted.mean(data[rows, 1], data[rows, 2])
}
values <- vapply(indices, fun, numeric(1))
labels <- myDF[match(seq_len(attr(ids, "n")), ids),
c("year", "state", "group1", "group2")]
aggregateDF <- cbind(labels, values)
})
# user system elapsed
# 2.04 0.29 2.33
Это намного быстрее, потому что он избегает копирования данных, извлекая только подмножество, необходимое для каждого вычисления, когда оно вычисляется.Переключение данных в матричную форму дает еще один прирост скорости, поскольку поднабор матрицы выполняется намного быстрее, чем поднабор кадров данных.