Предположим, у меня большой набор данных, и я хочу применить операцию прокрутки в течение длительного периода, но хочу применить агрегирование только для небольшого числа точек данных. Могу ли я сделать это с pandas
?
Когда я пытаюсь применить срез для результата функции агрегирования, мне кажется, что я опоздал, и все вычисления уже произошли:
small = 10
big = 1000
bigger = 10000000
s = pd.Series(np.arange(bigger))
%time x = s.rolling(big).mean()
%time x = s.rolling(big).mean()[:-small]
Вывод этого:
CPU times: user 306 ms, sys: 162 ms, total: 467 ms
Wall time: 468 ms
CPU times: user 291 ms, sys: 127 ms, total: 418 ms
Wall time: 418 ms
В приведенном выше примере я надеялся, что второе временное выражение будет выполняться быстрее, поскольку мне нужно было только вычислить агрегацию по последним 10 точкам данных, но это заняло столько же времени, сколько и для его вычисления для 10 миллионов. .
Что я здесь не так делаю?
В моем реальном сценарии я использую rolling
и expanding
, поэтому я ищу решение, которое применимо к обоим. Кроме того, в моем примере big
почти совпадает с bigger
.
РЕДАКТИРОВАТЬ: Следующее иллюстрирует разницу в производительности расчета скользящего среднего по сравнению с расчетом без избыточных вычислений. Он рассчитывает наивный случай, решение по 3UqU57GnaX
, а также «ручной» расчет. Обратите внимание, что ручной расчет - это то, чего я надеюсь достичь в общем случае (очевидно, я не хочу вручную реализовывать каждую функцию агрегирования):
import pandas as pd
import numpy as np
small = 10
big = 10000000
bigger = 100000000
s = pd.Series(np.arange(bigger))
def adjusted_mean(current_mean, removed_element, new_element, length):
return current_mean + (new_element - removed_element) / length
def rolling_mean_optimisation(small, big):
current_mean = s[-big-small:-small].mean()
return [adjusted_mean(current_mean, s.values[-big-x], s.values[-x], big) for x in range(small, 0, -1)]
%time naive = s.rolling(big).mean()[-small:]
%time answer_by_3UqU57GnaX = s[-big-small:].rolling(big).mean()[-small:]
%time manual_mean_optimisation = rolling_mean_optimisation(small, big)
Хотя ответ 3UqU57GnaX
является большим улучшением по сравнению с наивным случаем, ручная реализация все еще почти на порядок быстрее (фактическая сумма зависит от размера big
против bigger
:
CPU times: user 3.31 s, sys: 1.56 s, total: 4.87 s
Wall time: 4.88 s
CPU times: user 292 ms, sys: 154 ms, total: 446 ms
Wall time: 445 ms
CPU times: user 60.3 ms, sys: 21.2 ms, total: 81.4 ms
Wall time: 81.2 ms