似乎没有函数可以简单地计算numpy / scipy的移动平均值,从而导致解决方案复杂。
我的问题有两个:
一种简单的方法是使用np.convolve。其背后的想法是利用离散卷积的计算方式,并使用它来返回 滚动平均值 。这可以通过np.ones对长度等于我们想要的滑动窗口长度的序列进行卷积来完成。
np.convolve
np.ones
为此,我们可以定义以下函数:
def moving_average(x, w): return np.convolve(x, np.ones(w), 'valid') / w
该函数将对序列x和长度为1的序列进行卷积w。请注意,选择的mode方式valid是仅对序列完全重叠的点给出卷积。
x
w
mode
valid
一些例子:
x = np.array([5,3,8,10,2,1,5,1,0,2])
对于具有窗口长度的移动平均值,2我们将有:
2
moving_average(x, 2) # array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])
对于一个长度的窗口4:
4
moving_average(x, 4) # array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2. ])
convolve
让我们更深入地了解离散卷积的计算方式。以下功能旨在复制np.convolve计算输出值的方式:
def mov_avg(x, w): for m in range(len(x)-(w-1)): yield sum(np.ones(w) * x[m:m+w]) / w
对于上面的相同示例,这还将产生:
list(mov_avg(x, 2)) # [4.0, 5.5, 9.0, 6.0, 1.5, 3.0, 3.0, 0.5, 1.0]
所以在每个步骤要做的是取一个数组与当前 窗口 之间的内积。在这种情况下,乘以np.ones(w)是多余的,因为我们直接取sum序列的。
np.ones(w)
sum
波纹管是一个示例,该示例说明了如何计算第一个输出,从而使输出更加清晰。假设我们需要一个窗口w=4:
w=4
[1,1,1,1] [5,3,8,10,2,1,5,1,0,2] = (1*5 + 1*3 + 1*8 + 1*10) / w = 6.5
并且以下输出将计算为:
[1,1,1,1] [5,3,8,10,2,1,5,1,0,2] = (1*3 + 1*8 + 1*10 + 1*2) / w = 5.75
依此类推,一旦执行了所有重叠操作,就返回序列的移动平均值。