Кажется, нет функции, которая просто вычисляет скользящее среднее на numpy / scipy, что приводит к запутанным решениям .
У меня двоякий вопрос:
- Какой самый простой способ (правильно) реализовать скользящую среднюю с помощью numpy?
- Поскольку это кажется нетривиальным и подверженным ошибкам, есть ли веская причина не включать батареи в этом случае?
python
numpy
scipy
time-series
moving-average
Goncalopp
источник
источник
Ответы:
Если вы просто хотите простой Невзвешенный скользящей средней, вы можете легко реализовать его
np.cumsum
, чтоможет бытьесть методы быстрее , чем БПФ на основе:РЕДАКТИРОВАТЬ Исправлено неправильное индексирование, обнаруженное Бином в коде. РЕДАКТИРОВАТЬ
Итак, я предполагаю, что ответ таков: это действительно легко реализовать, и, возможно, numpy уже немного раздут со специализированной функциональностью.
источник
ret[n:] -= ret[:-n]
НЕ ТАК ЖЕ какret[n:] = ret[n:] - ret[:-n]
. Я исправил код в этом ответе. Изменить: Нет, кто-то другой просто опередил меня.Отсутствие в NumPy конкретной функции, зависящей от предметной области, возможно, связано с дисциплиной и верностью основной команды NumPy основной директиве: предоставить тип N-мерного массива , а также функции для создания и индексации этих массивов. Как и многие другие основные задачи, эта не маленькая, и NumPy справляется с ней блестяще.
(Намного) больший SciPy содержит гораздо большую коллекцию предметно-ориентированных библиотек ( которые разработчики SciPy называют подпакетами ) - например, численная оптимизация ( оптимизация ), обработка сигналов ( сигнал ) и интегральное исчисление ( интегрирование ).
Я предполагаю, что функция, которую вы ищете, находится по крайней мере в одном из подпакетов SciPy ( возможно, scipy.signal ); тем не менее, я бы сначала посмотрел на коллекцию Scikit SciPy , определил соответствующий scikit (ы) и поищу там интересующую функцию.
Scikits - это независимо разработанные пакеты, основанные на NumPy / SciPy и предназначенные для определенной технической дисциплины (например, scikits-image , scikits-learn и т. Д.). Некоторые из них (в частности, потрясающий OpenOpt для числовой оптимизации) получили высокую оценку, зрелые проекты задолго до того, как они решили жить под относительно новой рубрикой scikits . На домашней странице Scikits указано около 30 таких scikits. , хотя по крайней мере некоторые из них больше не находятся в активной разработке.
Следование этому совету приведет вас к scikits-timeseries ; однако этот пакет больше не находится в активной разработке; Фактически, Pandas стал, AFAIK, де-факто библиотекой временных рядов, основанной на NumPy .
В Pandas есть несколько функций, которые можно использовать для расчета скользящей средней ; Самым простым из них, вероятно, является Rolling_mean , который вы используете так:
Теперь просто вызовите функцию Rolling_mean, передав объект Series и размер окна , который в моем примере ниже составляет 10 дней .
убедитесь, что это сработало - например, сравните значения 10-15 в исходной серии с новой серией, сглаженной скользящим средним
Функция Rolling_mean вместе с примерно дюжиной других функций неофициально сгруппированы в документации Pandas под рубрикой « подвижные оконные функции»; Вторая связанная группа функций в Pandas называется экспоненциально взвешенными функциями (например, ewma , которая вычисляет экспоненциально скользящее средневзвешенное значение). Тот факт, что эта вторая группа не включена в первую ( функции движущегося окна ), возможно, объясняется тем, что экспоненциально взвешенные преобразования не полагаются на окно фиксированной длины.
источник
Простой способ добиться этого - использовать
np.convolve
. Идея состоит в том, чтобы использовать способ вычисления дискретной свертки и использовать ее для получения скользящего среднего . Это можно сделать, свернув последовательностьnp.ones
с длиной, равной длине скользящего окна, которую мы хотим.Для этого мы могли бы определить следующую функцию:
Эта функция будет принимать свертку последовательности
x
и последовательность единиц длиныw
. Обратите внимание , что выбранныйmode
являетсяvalid
таким , что свертка произведение задается только для точек , где последовательности перекрываются полностью.Некоторые примеры:
Для скользящей средней с окном длины
2
:А для окна длиной
4
:Как
convolve
работает?Давайте более подробно рассмотрим способ вычисления дискретной свертки. Следующая функция предназначена для воспроизведения способа
np.convolve
вычисления выходных значений:Что для того же примера выше также даст:
Итак, что делается на каждом шаге, так это переместить внутренний продукт между массивом единиц и текущим окном . В этом случае умножение на
np.ones(w)
является излишним, поскольку мы напрямую беремsum
последовательность.Ниже приведен пример того, как вычисляются первые результаты, чтобы он был немного яснее. Предположим, нам нужно окно
w=4
:И следующий результат будет вычислен как:
И так далее, возвращая скользящее среднее значение последовательности после выполнения всех перекрытий.
источник
mode='valid'
можно заменить на'same'
. Как раз в этом случае крайние точки будут стремиться к нулю.Вот несколько способов сделать это, а также некоторые тесты. Лучшие методы - это версии, использующие оптимизированный код из других библиотек. Этот
bottleneck.move_mean
метод, наверное, самый лучший. Этотscipy.convolve
подход также очень быстрый, расширяемый, синтаксически и концептуально простой, но плохо масштабируется для очень больших значений окна.numpy.cumsum
Метод хорош , если вам нужен чистыйnumpy
подход.Примечание. Некоторые из них (например
bottleneck.move_mean
) не центрированы и будут сдвигать ваши данные.Время, маленькое окно (n = 3)
Время, большое окно (n = 1001)
Память, маленькое окно (n = 3)
Память, большое окно (n = 1001)
источник
Этот ответ с использованием Pandas адаптирован сверху, поскольку
rolling_mean
больше не является частью PandasТеперь просто вызовите функцию
rolling
в фрейме данных с размером окна, который в моем примере ниже составляет 10 дней.источник
Я считаю, что это легко решить с помощью узкого места
См. Базовый образец ниже:
Это дает среднее значение перемещения по каждой оси.
«мм» - скользящее среднее для «а».
«окно» - это максимальное количество записей, которые следует учитывать для скользящего среднего.
«min_count» - это минимальное количество записей, которые следует учитывать для скользящего среднего (например, для первого элемента или если массив имеет значения nan).
Хорошая часть заключается в том, что «Узкое место» помогает справиться со значениями наночастиц, а также очень эффективно.
источник
В случае, если вы хотите тщательно позаботиться о краевых условиях ( вычислить среднее значение только из доступных элементов на краях ), следующая функция поможет.
источник
Попробуйте этот фрагмент кода. Я думаю, что это проще и работает. Lookback - это окно скользящей средней.
В поле
Data[i-lookback:i, 0].sum()
я указал0
для ссылки на первый столбец набора данных, но вы можете поместить любой столбец, который вам нравится, если у вас более одного столбца.источник
На самом деле мне хотелось немного другого поведения, чем принятый ответ. Я создавал средство извлечения скользящего среднего для
sklearn
конвейера, поэтому мне потребовалось, чтобы выходные данные скользящего среднего имели тот же размер, что и входные. Я хочу, чтобы скользящая средняя предполагала, что серия остается постоянной, то есть скользящая средняя[1,2,3,4,5]
с окном 2 даст[1.5,2.5,3.5,4.5,5.0]
.Для векторов-столбцов (мой вариант использования) мы получаем
А для массивов
Конечно, не обязательно принимать постоянные значения для заполнения, но в большинстве случаев этого должно быть достаточно.
источник
Talib содержит простой инструмент скользящего среднего, а также другие аналогичные инструменты усреднения (например, экспоненциальное скользящее среднее). Ниже сравнивается метод с некоторыми другими решениями.
Одно предостережение заключается в том, что в настоящем должны быть элементы
dtype = float
. В противном случае возникает следующая ошибкаисточник
Вот быстрая реализация с использованием numba (обратите внимание на типы). Обратите внимание, что там со смещением есть nans.
источник
источник
Я использую либо решение принятого ответа , слегка измененное, чтобы иметь ту же длину для вывода, что и ввод, либо
pandas
версию, указанную в комментарии к другому ответу. Я резюмирую их здесь с помощью воспроизводимого примера для использования в будущем:источник
Сравнивая решение ниже с тем, которое использует cumsum of numpy, это занимает почти половину времени . Это связано с тем, что не нужно проходить через весь массив, чтобы произвести суммирование, а затем выполнять все вычитание. Более того, cumsum может быть « опасным », если массив огромен, а число огромно ( возможно переполнение ). Конечно, и здесь опасность существует, но по крайней мере суммируются только существенные числа.
источник