用一次迭代计算均值和方差

时间:2010-02-26 11:51:59

标签: python iterator

我有一个数字迭代器,例如一个文件对象:

f = open("datafile.dat")

现在我想计算:

mean = get_mean(f)
sigma = get_sigma(f, mean)

最佳实施是什么?假设文件很大,我想避免两次阅读。

8 个答案:

答案 0 :(得分:12)

如果要迭代一次,可以编写求和函数:

def mysum(l):
    s2 = 0
    s = 0
    for e in l:
        s += e
        s2 += e * e
    return (s, s2)

并在sigma函数中使用结果。

编辑:现在您可以像这样计算方差:(s2 - (s * s)/ N)/ N

考虑到@Adam Bowen的评论,
请记住,如果我们使用数学技巧并转换原始公式
我们可能会降低结果。

答案 1 :(得分:5)

我认为Nick D有正确答案。

假设你想要在文件的一次扫描中计算均值和方差(并且你真的不想要两个必须一个接一个地调用的函数),你可以收集它们的值和它们的总和正方形和它们使用这些总和(与读取元素的数量一起)来同时计算均值和方差。

有一些数值稳定性问题,但

中的想法

http://en.wikipedia.org/wiki/Computational_formula_for_the_variance

是您需要的基本成分。

有更多细节

http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

我建议你阅读“Naïve算法”。

希望这有帮助,

的Massimo

答案 2 :(得分:2)

从iterable中创建一个列表,或使用itertools.tee()

答案 3 :(得分:2)

您可以一次性计算两者。参见:

http://www.johndcook.com/standard_deviation.html

答案 4 :(得分:1)

我不确定有多少选择。

在任何情况下,您都必须重复两次数字,因为标准偏差需要每个值的平均值。

如果你有足够的内存,你可以通过在第一次迭代期间将文件加载到内存中来获得I / O访问权限,但这是关于它的IMO。

答案 5 :(得分:1)

由于我觉得在多个答案中散布着好的元素,我想总结一下:

  • 如果你的文件太大而不方便地适合内存,如果你想在方差中有一个很好的精度,你需要读取文件两次(一次通过,方差是两个大的差异数字,由于浮点限制而不准确)。请注意,您的操作系统可能会为第二次文件读取提供一些自动加速,因为在第二次传递期间它可能仍然在RAM中。

  • 如果您不关心方差的精确度,您只需在文件上迭代一次并计算Nick D建议的数量,并在Adam Bowen的评论中提供详细信息。

答案 6 :(得分:0)

你有两个解决方案

  1. 从迭代器中创建一个列表并根据需要循环它。缺点是内存中的所有内容,因此如果您的文件很大,则不适用。简单地使用itertools.tee也不会救你

  2. 没有其他解决方案,除非,您不需要将get_mean的输出传递给get_sigma,因为在这种情况下它们只能是连续的,但如果您删除此限制然后你可以使用线程并行运行这两个函数,并使用itertools.tee从一个

  3. 获得两个迭代器

答案 7 :(得分:0)

您可以以优雅的方式使用map reduce

示例是您想要获得其差异的列表

sample = [a,b,c,...]

mean = float(reduce(lambda x,y : x+y, sample)) / len(sample)

variance = reduce(lambda x,y: x+y, map(lambda xi: (xi-mean)**2, sample))/ len(sample)

简洁的代码:

variance = reduce(lambda x,y: x+y, map(lambda xi: (xi-(float(reduce(lambda x,y : x+y, sample)) / len(sample)))**2, sample))/ len(sample)