问题描述
似乎没有函数可以简单地计算 numpy/scipy 上的移动平均值,导致 复杂的解决方案.
There seems to be no function that simply calculates the moving average on numpy/scipy, leading to convoluted solutions.
我的问题有两个:
- 使用 numpy(正确)实现移动平均线的最简单方法是什么?
- 既然这看起来很重要且容易出错,那么是否有充分的理由不使用 在这种情况下包括电池?
推荐答案
一个简单的方法是使用 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
的序列的卷积.请注意,选择的mode
是valid
,因此卷积乘积仅针对序列完全重叠的点.
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.
这篇关于如何使用 python + NumPy/SciPy 计算滚动/移动平均值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!