【问题标题】:Weighted moving average in python with different width in different regionspython中不同区域宽度不同的加权移动平均线
【发布时间】:2018-06-09 17:58:19
【问题描述】:

我试图对高度振荡的数据进行振荡平均。振荡不均匀,初始区域的振荡较少。

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 值的情节。请帮忙...

【问题讨论】:

  • 您的问题有点过于笼统,而且面向数学,导致堆栈溢出。尝试以明确的预期结果编辑您的帖子(例如“我想生成一个由 bla bla bla 组成的列表”)。此外,您的功能范围也不清楚。 “return (bin_centers,bin_avg)”应该在函数中吗?
  • 我已经编辑了这个问题。您也可以参考链接的问题了解初始详细信息。

标签: python-3.x matplotlib


【解决方案1】:

以下 sn-p 应该或多或少地完成您尝试做的事情。您的代码中主要存在逻辑问题,x.any() &lt; 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()

但是,根据使用情况,您也可以直接实现移动平均:

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()

当然你可以自适应地改变a,例如取决于当地的差异。另请注意,这有一个先验的小偏差,具体取决于ax 中的步长。

【讨论】:

    猜你喜欢
    • 2013-09-02
    • 1970-01-01
    • 2018-05-09
    • 2021-07-10
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多