У меня есть data.table значений, для которых я вычисляю обобщенную статистику в цикле и пытаюсь объединить обобщенные результаты для дополнительной обработки. Однако в результате агрегации время обработки цикла неожиданно велико, и я ищу более быстрое решение.
Метод очень напоминает подход, обсужденный здесь ( Назначение вектора конкретной существующей строке таблицы данных в R ).
Код ( немного сокращен для удобства чтения, но компоненты материала сохранены иллюстративно):
library(data.table);
x <- data.table(matrix(double(),nrow=10000,ncol=120));
system.time({for (i in NROW(x):1) {
m <- matrix(rnorm(8*15),nrow=8,ncol=15);
}});
# user system elapsed
# 0.165 0.006 0.171
system.time({for (i in NROW(x):1) {
m <- matrix(rnorm(8*15),nrow=8,ncol=15);
as.list(t(m[1:8,]));
}});
# user system elapsed
# 0.245 0.001 0.249
system.time({for (i in NROW(x):1) {
m <- matrix(rnorm(8*15),nrow=8,ncol=15);
x[i,] <- as.list(t(m[1:8,]));
}});
# user system elapsed
# 36.227 0.682 37.529
# Obtain input data.table
inputdt <- fread('filename');
# Preallocate summary statistics aggregate
sumstatsdt <- data.table(matrix(double(),nrow=10000,ncol=120));
# Loop over input data.table (the *apply suite not suitable for mypkg::calcstats())
for (i in NROW(inputdt):1) {
# Produce a matrix of summary statistics for the row (of type double)
sumstat_matrix <- mypkg::calcstats(inputdt,...);
# Aggregate the summary statistics (where "a","b","c",... are matrix row names of ordered statistics)
# >>>> This is the operation that leads to lengthy execution time
sumstatsdt[i,] <- as.list(t(sumstat_matrix[c("a","b","c",...),]));
};
Входной файл data.table содержит 10 000 наблюдений с 8 атрибутами, и в общей сложности необходимо сохранить 1,2 миллиона сводных статистических данных (каждый из которых имеет тип «double»). При комментировании последней строки в цикле, который выполняет агрегирование, общее время обработки составляет около 24 сек . При запуске с агрегацией общее время обработки увеличивается до 34 мин .
Я пытался использовать сопоставимый код с data.frame
и cbind()
со слабо похожими результатами производительности (у меня не было возможности попробовать tidyverse
suite). Признайте, что операции глубокого копирования будут несколько медленнее, хотя величина разницы во времени выполнения, учитывая относительно небольшой набор данных, кажется, указывает на другую проблему.
Запуск R v3.4.4, data.table v1.11.4 при последней установке Fedora. Использование памяти незначительно (менее 3% системной памяти используется во время выполнения сценария R). Один из процессоров с тактовой частотой 2,1 ГГц со сродством к сеансу R работает почти на 100% в течение всего времени выполнения сценария. Других процессов, связанных с этим ядром, нет, а остальные ядра в основном простаивают. ( NB : иллюстративный код, запускаемый в гостевой системе KVM на другом компьютере)
Sidenote: Также любопытно, почему узкое место ЦП проявляется в том, что в противном случае является проблемой с памятью.
Цените время и с радостью предоставлю дополнительную полезную информацию.
Редактировать [2018.10.31]
- Включите иллюстративный код, запрашиваемый 42