不同地区不同宽度的蟒蛇加权移动平均值

时间:2018-06-09 07:39:37

标签: python-3.x matplotlib

我试图获得高振荡数据的振荡平衡。振荡不均匀,初始区域的振荡较少。

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

(原始数据文件很大,所以我无法上传)

我想对该函数进行加权移​​动平均并绘制它。最初功能的周期较大,所以我想在很长的时间间隔内获得平均值。虽然我可以用更小的时间间隔做后者。

我在以下帖子中找到了一个可能优雅的解决方案:

Weighted moving average in python

但是,我想在x的不同区域有不同的宽度。假设当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)

毋庸置疑,这不起作用!我得到了sigma的第一个值的情节。请帮忙......

1 个答案:

答案 0 :(得分:1)

以下代码段应该或多或少地执行您尝试执行的操作。您的代码中主要存在逻辑问题,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中的步长,具有较小的偏差。