Взвешенное скользящее среднее в питоне с разной шириной в разных регионах - PullRequest
0 голосов
/ 09 июня 2018

Я пытался усвоить средние колебательные данные.Колебания неоднородны, в начальных областях меньше колебаний.

x = np.linspace(0, 1000, 1000001)
y = some oscillating data say, sin(x^2)

(Исходный файл данных огромен, поэтому я не могу его загрузить)

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

Я нашел возможное элегантное решение в следующем посте:

Взвешенное скользящее среднее в python

Однако я хочу иметь различную ширину в разныхобласти х.Скажем, когда x между (0,100), я хочу, чтобы ширина = 0,6, а когда x между (101, 300), ширина = 0,2 и т. Д.

Это то, что я пытался реализовать (с моим ограниченнымзнания в программировании!)

def weighted_moving_average(x,y,step_size=0.05):#change the width to control average
    bin_centers  = np.arange(np.min(x),np.max(x)-0.5*step_size,step_size)+0.5*step_size
    bin_avg = np.zeros(len(bin_centers))

    #We're going to weight with a Gaussian function
    def gaussian(x,amp=1,mean=0,sigma=1):
         return amp*np.exp(-(x-mean)**2/(2*sigma**2))


    if x.any()  < 100:
        for index in range(0,len(bin_centers)):
            bin_center = bin_centers[index]
            weights = gaussian(x,mean=bin_center,sigma=0.6)
            bin_avg[index] = np.average(y,weights=weights)

    else:
        for index in range(0,len(bin_centers)):
            bin_center = bin_centers[index]
            weights = gaussian(x,mean=bin_center,sigma=0.1)
            bin_avg[index] = np.average(y,weights=weights)

    return (bin_centers,bin_avg)

Нет необходимости говорить, что это не работает!Я получаю сюжет с первым значением сигмы.Пожалуйста, помогите ...

1 Ответ

0 голосов
/ 09 июня 2018

Следующий фрагмент должен делать более или менее то, что вы пытались сделать.В вашем коде в основном логическая проблема: x.any() < 100 всегда будет True, поэтому вы никогда не будете выполнять вторую часть.

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 1000)
y = np.sin(x**2)

def gaussian(x,amp=1,mean=0,sigma=1):
    return amp*np.exp(-(x-mean)**2/(2*sigma**2))

def weighted_average(x,y,step_size=0.3):
    weights = np.zeros_like(x)
    bin_centers  = np.arange(np.min(x),np.max(x)-.5*step_size,step_size)+.5*step_size
    bin_avg = np.zeros_like(bin_centers)

    for i, center in enumerate(bin_centers):
        # Select the indices that should count to that bin
        idx = ((x >= center-.5*step_size) & (x <= center+.5*step_size))

        weights = gaussian(x[idx], mean=center, sigma=step_size)
        bin_avg[i] = np.average(y[idx], weights=weights)
    return (bin_centers,bin_avg)

idx = x <= 4
plt.plot(*weighted_average(x[idx],y[idx], step_size=0.6))

idx = x >= 3
plt.plot(*weighted_average(x[idx],y[idx], step_size=0.1))

plt.plot(x,y)
plt.legend(['0.6', '0.1', 'y'])
plt.show()

enter image description here

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

x = np.linspace(0, 60, 1000)
y = np.sin(x**2)

z = np.zeros_like(x)
z[0] = x[0]

for i, t in enumerate(x[1:]):
    a=.2
    z[i+1] = a*y[i+1] + (1-a)*z[i]

plt.plot(x,y)
plt.plot(x,z)
plt.legend(['data', 'moving average'])
plt.show()

enter image description here

Конечно, вы можете изменить a адаптивно, например, в зависимости от локальной дисперсии.Также обратите внимание, что это имеет небольшой сдвиг в зависимости от a и размера шага в x.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...