在Python中为生成器计算均值

18 投票
10 回答
17259 浏览
提问于 2025-04-16 11:36

我正在做一些统计工作,我有一大堆随机数需要计算平均值。我想用生成器来处理这些数据,因为我只需要计算平均值,所以不需要存储这些数字。

问题是,如果你把生成器传给numpy.mean,它就会出错。我可以写一个简单的函数来实现我的需求,但我在想有没有更合适的内置方法来做到这一点?

如果我能说“sum(values)/len(values)”就好了,但len对生成器不管用,而sum已经把值消耗掉了。

这里有个例子:

import numpy 

def my_mean(values):
    n = 0
    Sum = 0.0
    try:
        while True:
            Sum += next(values)
            n += 1
    except StopIteration: pass
    return float(Sum)/n

X = [k for k in range(1,7)]
Y = (k for k in range(1,7))

print numpy.mean(X)
print my_mean(Y)

这两种方法都能得到相同的正确答案,但我的my_mean不适用于列表,而numpy.mean不适用于生成器。

我真的很喜欢使用生成器的想法,但像这样的细节似乎让事情变得复杂了。

10 个回答

8
def my_mean(values):
    total = 0
    for n, v in enumerate(values, 1):
        total += v
    return total / n

print my_mean(X)
print my_mean(Y)

在Python 3.4中,有一个叫做 statistics.mean() 的功能,但它会对输入的数据使用 调用 list()

def mean(data):
    if iter(data) is data:
        data = list(data)
    n = len(data)
    if n < 1:
        raise StatisticsError('mean requires at least one data point')
    return _sum(data)/n

这里的 _sum() 函数可以准确地计算总和(类似于 math.fsum() 的功能,它除了支持 float 类型外,还支持 FractionDecimal 类型)。

28

一般来说,如果你要计算一串浮点数的平均值,使用一个更稳定的算法会比简单地把所有数加起来再除以数量要好。

我知道的最简单的算法通常被认为是克努斯(Knuth)提出的,它还可以计算方差。链接里有一个Python的实现,不过这里为了完整性,单独把计算平均值的部分贴出来。

def mean(data):
    n = 0
    mean = 0.0
 
    for x in data:
        n += 1
        mean += (x - mean)/n

    if n < 1:
        return float('nan')
    else:
        return mean

我知道这个问题已经很久了,但它在谷歌上还是第一个搜索结果,所以我觉得有必要发一下。我还是觉得很遗憾,Python的标准库里没有这个简单的代码。

8

只需要对你的代码做一个简单的修改,就可以同时使用这两者。生成器的设计初衷就是可以在for循环中和列表互换使用。

def my_mean(values):
    n = 0
    Sum = 0.0
    for v in values:
        Sum += v
        n += 1
    return Sum / n

撰写回答