Двусторонняя скользящая средняя в питоне - PullRequest
0 голосов
/ 17 мая 2019

Привет, у меня есть некоторые данные, и я хочу вычислить центрированную скользящую среднюю или двустороннюю скользящую среднюю.

Я понял, насколько легко это можно сделать с помощью функции numpy.convolve, и мне интересно,Существует простой или аналогичный способ, которым это можно сделать, но когда среднее значение должно быть двусторонним.

Одностороннее скользящее среднее обычно работает следующим образом, если интервал содержит три записи, N = 3:

import numpy
list = [3, 4, 7, 8, 9, 10]
N = 3
window = numpy.repeat(1., N)/N
moving_avg = numpy.convolve(list, window, 'valid')
moving_avg = array([ 4.66666667,  6.33333333,  8.        ,  9.        ])

Теперь я стремлюсь получить среднее значение с центром, так что если N = 3, интервалы, по которым берется среднее значение, составляют: [[3, 4, 7], [4, 7, 8], [7, 8, 9], [8, 9, 10]].Это также сложно, если N четное число.Есть ли инструмент для вычисления этого?Я бы предпочел сделать это, написав функцию или используя numpy.

1 Ответ

1 голос
/ 17 мая 2019

Как и комментаторы, я также запутался в том, что вы пытаетесь достичь, оно отличается от того, что вы продемонстрировали.

В любом случае я хотел предложить решение, которое позволит вам писать собственные операции свертки, используя Numba's @stencil decorator :

from numba import stencil

@stencil
def ma(a):
    return (a[-1] + a[0] + a[1]) / 3

data = np.array([3, 4, 7, 8, 9, 10])
print(ma(data))
[0.         4.66666667 6.33333333 8.         9.         0.        ]

Не уверен, что это именно то, что вы ищете, но оператор трафарета великолепен. Переменная, которую вы передаете, представляет данный элемент, и любая используемая вами индексация относится к этому элементу. Как видите, было достаточно легко создать окно из 3 элементов для вычисления скользящего среднего.

Надеюсь, это даст вам то, что вам нужно.

Использование большого соседства

Вы можете добавить параметр в трафарет, который является включающим. Давайте сделаем окрестности 9:

@stencil(neighborhood = ((-4, 4),))
def ma(a):
    cumul = 0
    for i in range(-4, 5):
        cumul += a[i]
    return cumul / 9

Вы можете сместить диапазон вперед или назад с помощью (-8, 0) или (0, 8) и изменить диапазон.

Настройка N Окрестности

Не уверен, что это лучший способ, но я сделал это с помощью обертки:

def wrapper(data, N):
    @nb.stencil(neighborhood = ((int(-(N-1)/2), int((N-1)/2)),))
    def ma(a):
        cumul = 0
        for i in np.arange(int(-(N-1)/2), int((N-1)/2)+1):
            cumul += a[i]
        return cumul / N
    return ma(data)

Опять же, индексация странная, поэтому вам придется поиграть с ней, чтобы получить желаемый эффект.

...