Reputation: 9
First time Python user and I am lost. I need to create a table from a list that displays the daily temperature and the running average of temperature up to that day.
xData = arange(1,32)
tData = [86,87,84,86,86,86,84,83,90,89,88,85,86,79,83,81, \
75,80,81,85,81,88,89,87,84,85,86,88,88,90,90]
avg = [86.] # First value for monthly avg high temp is just the Day 1 temp
Upvotes: 0
Views: 898
Reputation: 147
Here's a way to do it using itertools and operators
from itertools import starmap, accumulate
from operator import add
def moving_average(data):
moving_sum = enumerate(accumulate(data, add)), start=1)
return starmap(lambda index, elem: elem / index, moving_sum)
Upvotes: 0
Reputation: 366213
A running average is just, for each value in a list, the average of all of the values up to that one. For a stripped-down version of your example:
>>> tData = [86,87,84,86]
The running averages are 86/1
, (86+87)/2
, (86+87+84)/3
, and (86+87+84+86)/4
.
So, at each index, the running average is the running total, dividing by (index + 1).
You can get the running totals with accumulate
:
>>> list(accumulate(tData))
[86, 173, 257, 343]
And you can get the (1-based) indexes with enumerate
:
>>> list(enumerate(accumulate(tData, start=1))
[(1, 86), (2, 73), (3, 257), (4, 343)]
So, just divide:
>>> [total / index for index, total in enumerate(accumulate(tData, start=1))]
[86.0, 86.5, 85.66666666666667, 85.75]
Or using statistics
in Python 3.4, or its backport/predecessor stats
for 3.1-3.3:
>>> from stats import running_average
>>> running_average(tData)
[86, 86.5, 85.66666666666667, 85.75]
Of course you can always do it explicitly if you prefer:
>>> running_sum, running_sums = 0, []
>>> for value in tData:
... running_sum += value
... running_sum.append(running_sum)
>>> [value / index for index, value in enumerate(running_sums, start=1)]
[86, 86.5, 85.66666666666667, 85.75]
… or even:
>>> running_sum, running_averages = 0, []
>>> for index, value in enumerate(tData, start=1):
... running_sum += value
... running_averages.append(running_sum / index)
>>> running_averages
[86, 86.5, 85.66666666666667, 85.75]
Upvotes: 5
Reputation: 49063
Here's another way to do it:
def cumSeries(series):
result = [0]
for s in series:
result.append(s + result[-1])
return result
def runningAvg(series):
cs = cumSeries(series)
return [(cs[i] - cs[0]) / float(i) for i in range(1, len(cs))]
tData = [86,87,84,86,86,86,84,83,90,89,88,85,86,79,83,81, \
75,80,81,85,81,88,89,87,84,85,86,88,88,90,90]
print runningAvg(tData)
Using cumulative series is a very useful way of working with sums over parts of a series.
Upvotes: 0
Reputation: 49063
I'd go with this:
def runningAvgs(data):
avg = data[0]
for i, d in enumerate(data[1:], start=1):
yield avg
avg = ((i * avg) + d) / (i + 1.0)
yield avg
tData = [86,87,84,86,86,86,84,83,90,89,88,85,86,79,83,81, \
75,80,81,85,81,88,89,87,84,85,86,88,88,90,90]
print list(runningAvgs(tData))
Upvotes: 0