Kara - 6 months ago 62

Python Question

Let's say I have a list:

`y = ['1', '2', '3', '4','5','6','7','8','9','10']`

I want to create a function that calculates the moving n-day average.

So if

`n`

I don't want to calculate the first n-1 days, so starting from the nth day, it'll count the previous days.

`def moving_average(x:'list of prices', n):`

for num in range(len(x)+1):

print(x[num-n:num])

This seems to print out what I want:

`[]`

[]

[]

[]

[]

['1', '2', '3', '4', '5']

['2', '3', '4', '5', '6']

['3', '4', '5', '6', '7']

['4', '5', '6', '7', '8']

['5', '6', '7', '8', '9']

['6', '7', '8', '9', '10']

However, I don't know how to calculate the numbers inside those lists. Any ideas?

Answer

There is a great sliding window generator in an old version of the Python docs with `itertools`

examples:

```
from itertools import islice
def window(seq, n=2):
"Returns a sliding window (of width n) over data from the iterable"
" s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ... "
it = iter(seq)
result = tuple(islice(it, n))
if len(result) == n:
yield result
for elem in it:
result = result[1:] + (elem,)
yield result
```

Using that your moving averages is trivial:

```
from __future__ import division # For Python 2
def moving_averages(values, size):
for selection in window(values, size):
yield sum(selection) / size
```

Running this against your input (mapping the strings to integers) gives:

```
>>> y= ['1', '2', '3', '4','5','6','7','8','9','10']
>>> for avg in moving_averages(map(int, y), 5):
... print(avg)
...
3.0
4.0
5.0
6.0
7.0
8.0
```

To return `None`

the first `n - 1`

iterations for 'incomplete' sets, just expand the `moving_averages`

function a little:

```
def moving_averages(values, size):
for _ in range(size - 1):
yield None
for selection in window(values, size):
yield sum(selection) / size
```