在Python中为生成器计算均值
我正在做一些统计工作,我有一大堆随机数需要计算平均值。我想用生成器来处理这些数据,因为我只需要计算平均值,所以不需要存储这些数字。
问题是,如果你把生成器传给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
类型外,还支持 Fraction
和 Decimal
类型)。
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