翻阅古今
如果你只是想要一个简单的非加权移动平均线,您可以轻松地实现它np.cumsum,这可能 是比基于FFT方法快:编辑纠正了代码中Bean发现的一个错误的索引。编辑def moving_average(a, n=3) : ret = np.cumsum(a, dtype=float) ret[n:] = ret[n:] - ret[:-n] return ret[n - 1:] / n>>> a = np.arange(20)>>> moving_average(a)array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18.])>>> moving_average(a, n=4)array([ 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5])所以我猜答案是:它实现起来非常简单,而且numpy可能已经变得有点臃肿了。
慕后森
实现这一目标的一种简单方法是使用np.convolve。这背后的想法是利用计算离散卷积的方式,并使用它来返回滚动均值。这可以通过卷积np.ones一个长度等于我们想要的滑动窗口长度的序列来完成。为此,我们可以定义以下函数:def moving_average(x, w): return np.convolve(x, np.ones(w), 'valid') / w该函数将对序列x和一系列长度进行卷积w。请注意,所选择的mode是valid仅对序列完全重叠的点给出卷积乘积。用例一些例子:x = np.array([5,3,8,10,2,1,5,1,0,2])对于具有长度窗口的移动平均线,2我们将:moving_average(x, 2)# array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])并为一个长度的窗口4:moving_average(x, 4)# array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2. ])细节让我们更深入地了解计算离散卷积的方式。以下函数旨在复制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]因此,在每一步中所做的是在1的数组和当前窗口之间获取内积。在这种情况下,乘法np.ones(w)是多余的,因为我们直接采用sum序列。贝娄是如何计算第一个输出以使其更清晰的一个例子。让我们想要一个窗口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依此类推,一旦完成所有重叠,就返回序列的移动平均值。