Fix Python – How to calculate rolling / moving average using python + NumPy / SciPy?

Question

Asked By – loopbackbee

There seems to be no function that simply calculates the moving average on numpy/scipy, leading to convoluted solutions.

My question is two-fold:

• What’s the easiest way to (correctly) implement a moving average with numpy?
• Since this seems non-trivial and error prone, is there a good reason not to have the batteries included in this case?

Now we will see solution for issue: How to calculate rolling / moving average using python + NumPy / SciPy?

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
``````

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.

Some examples:

``````x = np.array([5,3,8,10,2,1,5,1,0,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. ])
``````

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

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]
``````

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 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
``````

And the following output would be computed as:

``````  [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.

This question is answered By – yatu

This answer is collected from stackoverflow and reviewed by FixPython community admins, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0