У меня есть алгоритм, который требует, чтобы изменяющийся вектор 'wgts' из N чисел суммировался в соответствии с категориями в матрице M-by-N целых чисел 'bin'.Например, если начальные значения «wgts» равны [0,2, 0,4, 0,3, 0,1, 0,7, 0,6], а B равно [[0, 1, 2, 2, 0, 1], [2, 2, 0,0, 1, 1]], результат будет [[(0,2 + 0,7), (0,4 + 0,6), (0,3 + 0,1)], [(0,7 + 0,6), (0,2 + 0,4), (0,3 + 0,1))]
Мне нужно повторить этот процесс с матрицей фиксированной категории 'bin' и изменением вектора 'wgts'.Поскольку M и N становятся большими, этот процесс занимает много времени.Я обнаружил, что пакет Python Numpy имеет полезную и быструю привязку функций для этого.Я хотел бы использовать R, поскольку остальная часть моего процесса находится в R, но пока я не могу исправить свой алгоритм в R так же быстро, как в Python
Подход в R, который, кажется, работаетдо сих пор быстрее всего сохранять отдельные логические матрицы M-N, по одной для каждой категории.Тем не менее, он все равно занимает примерно вдвое больше времени, чем мой скрипт на Python, и я предполагаю, что он требует больше памяти, хотя я не уверен, как измерить эту часть.Ниже приведены сценарии Python и R. с указанием времени их обработки.
# R First attempt, "straightforward"
smplSize <- 1000000
binTypes <- 100
nIter <- 20
set.seed(1)
bins <- matrix(floor(runif(smplSize * binTypes, min=0, max=5)),
nrow = smplSize)
wgts <- runif(smplSize)
tic <- Sys.time()
for (i in (1:nIter)) {
res <- matrix(nrow=5, ncol=binTypes)
for (j in 0:4) {
res[j+1,] <- colSums(wgts * (bins == j))
}
# Some process that modifies wgts based on res
}
toc <- Sys.time()
toc - tic # 117 seconds
# Second attempt, storing category locations in separate mask matrices
tic <- Sys.time()
# Store 5 matrices identifying locations of the integers 0 - 4
binMask <- list()
for (i in 0:4) {
binMask[[i+1]] <- bins == i
}
for (i in (1:nIter)) {
res <- matrix(nrow=5, ncol=binTypes)
for (j in 0:4) {
res[j+1,] <- colSums(wgts * binMask[[j + 1]])
}
# Some process that modifies wgts based on res
}
toc <- Sys.time()
toc - tic # 72 seconds
print(object.size(binMask), units = "Gb") # 1.9 Gb
import numpy as np
import timeit
import sys
smplSize = 1000000
nBins = 100
nIter = 20
wgts = np.random.random_sample(smplSize)
bins = np.random.randint(0, 5, (smplSize, nBins))
tic=timeit.default_timer()
res = np.bincount(bins, wgts)
toc=timeit.default_timer()
toc - tic
tic=timeit.default_timer()
for i in range(nIter):
res = np.apply_along_axis(np.bincount, 0, bins, wgts)
toc=timeit.default_timer()
toc - tic # 39 seconds
sys.getsizeof(bins)/(1024 ** 2) # 381 Mb
Я использую R 3.4.4 и Python 3.6.1 на 64-разрядном компьютере под управлением Windows, процессор Intel XeonE5-2680, 96 ГБ ОЗУ.
Я смотрел, как Python как-то кеширует вычисления, но это не так.
Я немного поиграл с data.table 'group' вычислениями, но я не нашел хорошего способа обработки нескольких столбцов для группировки.
В R для проверки точности вычислений значение res [1, 1] равно 99967.64