Взвешенное сглаживание одномерного массива — Python

Я новичок в Python, и у меня есть массив обнаружений некоторых параметров, некоторые значения были обнаружены неправильно и (например, 4555555):

array = [1, 20, 55, 33, 4555555, 1]

И я хочу как-то это сгладить. Прямо сейчас я делаю это со средневзвешенным значением:

def smoothify(array):
    for i in range(1, len(array) - 2):
        array[i] = 0.7 * array[i] + 0.15 * (array[i - 1] + array[i + 1])
    return array

Но это работает довольно плохо, конечно, мы можем взять среднее взвешенное более чем из 3 элементов, но это приводит к копипасту... Я пытался найти какие-то нативные функции для этого, но у меня не получилось.

Не могли бы вы помочь мне с этим?

P.S. Извините, если это нубский вопрос :(

Спасибо за ваше время, С уважением, Анна


person Anna Sviridova    schedule 05.02.2016    source источник


Ответы (4)


Предложил бы numpy.average, чтобы помочь ты с этим. хитрость заключается в том, чтобы рассчитать веса — ниже я заархивирую три списка — один такой же, как исходный массив, следующий на шаг впереди, следующий на шаг позади. Получив веса, мы передаем их в функцию np.average.

import numpy as np
array = [1, 20, 55, 33, 4555555, 1]
arrayCompare = zip(array, array[1:] + [0], [0] + array)

weights = [.7 * x + .15 * (y + z) for x, y, z in arrayCompare]

avg = np.average(array, weights=weights)
person nlloyd    schedule 05.02.2016

В целях взвешенного сглаживания вы в основном хотите выполнить convolution. В нашем случае, поскольку мы имеем дело с одномерными массивами, мы можем просто использовать функцию одномерной свертки NumPy: np.convolve для векторизованного решения. Единственная важная вещь, которую нужно помнить, это то, что веса должны быть обращены, учитывая природу свертки, которая использует обращенную версию ядра, которая скользит по основному входному массиву. Таким образом, решение будет -

weights = [0.7,0.15,0.15]
out = np.convolve(array,np.array(weights)[::-1],'same')

Если вы хотите получить средневзвешенное значение, вы можете получить те, у которых есть out/sum(weights). В нашем случае, поскольку сумма заданных весов уже равна 1, вывод останется таким же, как out.

Давайте построим вывод вместе с вводом для графической отладки -

# Input array and weights
array = [1, 20, 55, 33, 455, 200, 100, 20 ]
weights = [0.7,0.15,0.15]

out = np.convolve(array,np.array(weights)[::-1],'same')

x = np.arange(len(array))
f, axarr = plt.subplots(2, sharex=True, sharey=True)
axarr[0].plot(x,array)
axarr[0].set_title('Original and smoothened arrays')
axarr[1].plot(x,out)

Выход -

введите описание изображения здесь

person Divakar    schedule 06.02.2016

Возможно, вы хотите взглянуть на numpy и, в частности, на numpy .среднее. Кроме того, вы видели этот вопрос Взвешенное скользящее среднее в python? Тоже может быть полезно.

person Jesper Freesbug    schedule 05.02.2016

Поскольку вы пометили это с помощью numpy, я написал, как бы я сделал это с помощью numpy:

import numpy as np

def smoothify(thisarray):
    """
    returns moving average of input using:
    out(n) = .7*in(n) + 0.15*( in(n-1) + in(n+1) )
    """

    # make sure we got a numpy array, else make it one
    if type(thisarray) == type([]): thisarray = np.array(thisarray)

    # do the moving average by adding three slices of the original array
    # returns a numpy array,
    # could be modified to return whatever type we put in...
    return 0.7 * thisarray[1:-1] + 0.15 * ( thisarray[2:] + thisarray[:-2] )

myarray = [1, 20, 55, 33, 4555555, 1]
smootharray = smoothify(myarray)

Вместо того, чтобы перебирать исходный массив, с помощью numpy вы можете получить «фрагменты» путем индексации. Выходной массив будет на два элемента короче входного массива. Центральными точками (n) являются thisarray[1:-1] : «От индекса элемента 1 до последнего элемента (не включительно)». Другие фрагменты: «От индекса 2 до конца» и «Все, кроме двух последних».

person 22degrees    schedule 05.02.2016