且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-12-20 07:48:40

一个简单的方法是使用 np.convolve.这背后的想法是利用 离散卷积 的计算方式并使用它返回滚动平均值.这可以通过对一系列 np.ones 长度等于我们想要的滑动窗口长度.

A simple way to achieve this is by using np.convolve. The idea behind this is to leverage the way the discrete convolution is computed and use it to return a rolling mean. This can be done by convolving with a sequence of np.ones of a length equal to the sliding window length we want.

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

In order to do so we could define the following function:

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

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

This function will be taking the convolution of the sequence x and a sequence of ones of length w. Note that the chosen mode is valid so that the convolution product is only given for points where the sequences overlap completely.

一些例子:

x = np.array([5,3,8,10,2,1,5,1,0,2])

对于窗口长度为 2 的移动平均线,我们将有:

For a moving average with a window of length 2 we would have:

moving_average(x, 2)
# array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])

对于长度为 4 的窗口:

And for a window of length 4:

moving_average(x, 4)
# array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2.  ])

卷积是如何工作的?

让我们更深入地了解离散卷积的计算方式.以下函数旨在复制 np.convolve 计算输出值的方式:


How does convolve work?

Lets have a more in depth look at the way the discrete convolution is being computed. The following function aims to replicate the way np.convolve is computing the output values:

def mov_avg(x, w):
    for m in range(len(x)-(w-1)):
        yield sum(np.ones(w) * x[m:m+w]) / w 

对于上面的相同示例,也将产生:

Which, for the same example above would also yield:

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.

So what is being done at each step is to take the inner product between the array of ones and the current window. In this case the multiplication by np.ones(w) is superfluous given that we are directly taking the sum of the sequence.

Bellow 是如何计算第一个输出的示例,以便更清楚一点.假设我们想要一个 w=4 的窗口:

Bellow is an example of how the first outputs are computed so that it is a little clearer. Lets suppose we want a window of 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

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

And so on, returning a moving average of the sequence once all overlaps have been performed.