如何使用 python NumPy / SciPy 计算滚动/移动平均值?

新手上路,请多包涵

似乎没有函数可以简单地计算 numpy/scipy 上的移动平均值,从而导致 复杂的解决方案

我的问题有两个:

  • (正确)使用 numpy 实现移动平均线的最简单方法是什么?
  • 既然这看起来不简单且容易出错,那么是否有充分的理由不将 电池包含 在这种情况下?

原文由 loopbackbee 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

实现此目的的一种简单方法是使用 np.convolve 。这背后的想法是利用计算 离散卷积 的方式并使用它来返回 _滚动平均值_。这可以通过与长度等于我们想要的滑动窗口长度的 np.ones 序列进行卷积来完成。

为此,我们可以定义以下函数:

 def moving_average(x, w):
    return np.convolve(x, np.ones(w), 'valid') / w

此函数将采用序列 x 和长度为 w 的序列的卷积。请注意,选择的 modevalid 以便仅对序列完全重叠的点给出卷积乘积。


一些例子:

 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.  ])


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

Bellow 是如何计算第一个输出的示例,以便更清晰一些。假设我们想要一个 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

依此类推,一旦执行了所有重叠,就返回序列的移动平均值。

原文由 yatu 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您只想要一个简单的非加权移动平均线,您可以使用 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 已经有点臃肿的专门功能。

原文由 Jaime 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏