我试图获得高振荡数据的振荡平衡。振荡不均匀,初始区域的振荡较少。
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的第一个值的情节。请帮忙......
答案 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()
但是,根据使用情况,您还可以直接实施移动平均线:
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
,例如取决于局部方差。另请注意,这取决于a
以及x
中的步长,具有较小的偏差。