【问题标题】:Create a running average from a list从列表创建运行平均值
【发布时间】:2013-09-10 01:21:02
【问题描述】:

第一次使用 Python 用户,我迷路了。我需要从一个列表中创建一个表格,显示每日温度和截至当天的运行平均温度。

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

【问题讨论】:

  • 你卡在哪里了?你试过什么?
  • 我只是不知道如何开始,让它成为一个运行平均值。我知道如何做一个“常规”平均值,我只是不知道如何让它成为一个“运行平均值”
  • 什么版本的 Python?如果您可以等待 3.4,只需 import statistics,它是单行的。对于 3.1-3.3,您可以在 PyPI 上使用 the backport。否则,你得写几行代码。

标签: python moving-average


【解决方案1】:

对于列表中的每个值,运行平均值只是直到该值的所有值的平均值。对于您的示例的精简版本:

>>> tData = [86,87,84,86]

运行平均值为86/1(86+87)/2(86+87+84)/3(86+87+84+86)/4

因此,在每个索引处,运行平均值是运行总和,除以 (index + 1)。

您可以通过accumulate获取运行总数:

>>> list(accumulate(tData))
[86, 173, 257, 343]

您可以使用 enumerate 获取(基于 1 的)索引:

>>> list(enumerate(accumulate(tData, start=1))
[(1, 86), (2, 73), (3, 257), (4, 343)]

所以,只是划分:

>>> [total / index for index, total in enumerate(accumulate(tData, start=1))]
[86.0, 86.5, 85.66666666666667, 85.75]

或者在 Python 3.4 中使用 statistics,或者在 3.1-3.3 中使用它的后端/前身 stats

>>> from stats import running_average
>>> running_average(tData)
[86, 86.5, 85.66666666666667, 85.75]

当然,如果您愿意,您可以随时明确地这样做:

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

……甚至:

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

【讨论】:

  • +1。 enumerate 接受第二个参数作为起始值。如果你从 1 开始,那么你以后不需要添加它。 statistics 模块是最新的。你潜伏在 python 开发邮件列表中吗?
  • @StevenRumbalski:谢谢。我不知道我是如何忘记 start 参数的,但我已经更新了答案。我浏览了 python-dev 和 python-ideas 以跟上进度,偶尔也会在 PEP 列表中寻找新的东西。即使是被拒绝的提案也经常包含有趣的想法……
【解决方案2】:

我会选择这个:

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

【讨论】:

    【解决方案3】:

    这是另一种方法:

    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)
    

    使用累积系列是处理部分系列总和的非常有用的方法。

    【讨论】:

      【解决方案4】:

      这是一种使用itertoolsoperators 的方法

      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)
      

      【讨论】:

        猜你喜欢
        • 2012-08-15
        • 1970-01-01
        • 1970-01-01
        • 2016-01-21
        • 1970-01-01
        • 2020-08-22
        • 2021-12-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多