Какой самый быстрый способ подвести итоги по группам в R
? Я использовал data.table
, чтобы максимально оптимизировать этот шаг, но он по-прежнему остается основным узким местом в моем коде, поскольку его приходится запускать тысячи раз.
library(data.table)
data <- matrix(rnorm(5e6 * 16), ncol = 16)
colnames(data) <- paste0("mark", 1:16)
group <- gl(10, 5e5, labels = paste0("sample", 1:10))
DT <- data.table(group, data) # 1/10 actual row #
out <- DT[, lapply(.SD, function(x) {mean(x^3)}), by = group]
Никакой разницы с DT[, lapply(.SD, function(x) {mean(x^3)}), by = key(DT)]
. Тем не менее, хорошо знать, что кто-то еще пришел к такому же выводу
Если вы действительно пытаетесь выжать из этого немного скорости, я только что сравнил x*x*x
и x^3
с 1000 чисел, и первый работал примерно в 5 раз быстрее. Если вы суммируете менее 1000 чисел за раз, он никогда не будет медленнее, чем x^3
, и начинает показывать даже небольшое улучшение скорости всего лишь с 20+ числами.
Используйте подробное описание, чтобы убедиться, что оптимизация GForce запущена. Я не уверен, что он не будет отключен x^3 внутри. Затем вычислите это как новый столбец, а затем вызовите среднее значение для материализованного столбца.
Как отмечает r2evans, функция mean
— не самая медленная часть. Это функция мощности x^3
для всех данных.
Мы можем увидеть это, если разделим вызовы и замерим время.
system.time(x <- lapply(seq_along(DT)[-1], function(i) DT[[i]]^3)) # 4.7
system.time(setDT(x)) # 0
system.time(x[, lapply(.SD, mean), by = DT$group]) # 0.41
В данном конкретном случае могу предложить:
v2 <- function() {
x <- lapply(seq_along(DT)[-1], function(i) DT[[i]]*DT[[i]]*DT[[i]])
setDT(x)
x[, lapply(.SD, mean), by = DT$group]
}
время:
v1 <- function() {
DT[, lapply(.SD, function(x) {mean(x^3)}), by = group]
}
system.time(v1()) # 4.92
system.time(v2()) # 0.84
Также,
x[, lapply(.SD, mean), by = DT$group]
x[, lapply(.SD, function(i) mean(i)), by = DT$group]
разные. Первый вызывает data.tables
gmean
, а второй — нет. В зависимости от размера ваших данных один подход может быть быстрее, чем другой.
Вы правы, v2()
работает примерно в 2 раза быстрее, используя мой реальный набор данных. Интересно, что результаты v1 и v2 отличаются примерно на 2,740863e-16. Я предполагаю, что это связано с gmean
Трудно превзойти
data.table
- на R или любом другом языке. Эти тесты от H2O.AI показывают, чтоdata.table
побеждает или находится почти на первом месте в зависимости от размера данных / количества групп для сгруппированных сумм по сравнению сdplyr
или несколькими другими языковыми альтернативами, известными своей производительностью. Можете ли вы сначала установить ключ в data.table? Особенно, если вы выполняете другие сгруппированные операции, которые должны несколько ускорить процесс.