是否有python的scipy函数或numpy函数或模块来计算给定特定窗口的一维数组的运行平均值?
对于一个简短,快速的解决方案,它可以在一个循环中完成所有事情,而没有依赖关系,下面的代码效果很好。
mylist = [1, 2, 3, 4, 5, 6, 7] N = 3 cumsum, moving_aves = [0], [] for i, x in enumerate(mylist, 1): cumsum.append(cumsum[i-1] + x) if i>=N: moving_ave = (cumsum[i] - cumsum[i-N])/N #can do stuff with moving_ave here moving_aves.append(moving_ave)
高效的解决方案 卷积比简单方法好得多,但是(我猜)它使用FFT,因此速度很慢。但是专门用于计算运行,以下方法可以正常工作
def running_mean(x, N): cumsum = numpy.cumsum(numpy.insert(x, 0, 0)) return (cumsum[N:] - cumsum[:-N]) / float(N)
要检查的代码
In[3]: x = numpy.random.random(100000) In[4]: N = 1000 In[5]: %timeit result1 = numpy.convolve(x, numpy.ones((N,))/N, mode='valid') 10 loops, best of 3: 41.4 ms per loop In[6]: %timeit result2 = running_mean(x, N) 1000 loops, best of 3: 1.04 ms per loop
注意numpy.allclose(result1, result2)是True,这两种方法是等效的。N越大,时间差越大。
numpy.allclose(result1, result2)
True
N
UPD:Alleo和jasaarim提出了更有效的解决方案。
你可以使用np.convolve:
np.convolve
np.convolve(x, np.ones((N,))/N, mode='valid')
说明 运行平均值是卷积数学运算的一种情况。对于移动平均值,你可以沿输入滑动窗口并计算窗口内容的平均值。对于离散的一维信号,卷积是相同的事情,除了用平均值代替之外,你还可以计算任意线性组合,即将每个元素乘以相应的系数并相加结果。窗口中每个位置对应的那些系数有时称为卷积核。现在,N个值的算术平均值为(x_1 + x_2 + ... + x_N) / N,因此对应的内核为(1/N, 1/N, ..., 1/N),这正是我们使用所得到的np.ones((N,))/N。
(x_1 + x_2 + ... + x_N) / N
1/N, 1/N, ..., 1/N
边缘 的mode参数np.convolve指定如何处理边缘。我在valid这里选择此模式是因为我认为大多数人都希望运行平均值起作用,但是你可能还有其他优先事项。这是说明两种模式之间差异的图表:
import numpy as np import matplotlib.pyplot as plt modes = ['full', 'same', 'valid'] for m in modes: plt.plot(np.convolve(np.ones((200,)), np.ones((50,))/50, mode=m)); plt.axis([-10, 251, -.1, 1.1]); plt.legend(modes, loc='lower center'); plt.show()