我有一个数字迭代器,例如一个文件对象:
f = open("datafile.dat")
现在我想计算:
mean = get_mean(f)
sigma = get_sigma(f, mean)
最佳实施是什么?假设文件很大,我想避免两次阅读。
答案 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)
您可以一次性计算两者。参见:
答案 4 :(得分:1)
我不确定有多少选择。
在任何情况下,您都必须重复两次数字,因为标准偏差需要每个值的平均值。
如果你有足够的内存,你可以通过在第一次迭代期间将文件加载到内存中来获得I / O访问权限,但这是关于它的IMO。
答案 5 :(得分:1)
由于我觉得在多个答案中散布着好的元素,我想总结一下:
如果你的文件太大而不方便地适合内存,如果你想在方差中有一个很好的精度,你需要读取文件两次(一次通过,方差是两个大的差异数字,由于浮点限制而不准确)。请注意,您的操作系统可能会为第二次文件读取提供一些自动加速,因为在第二次传递期间它可能仍然在RAM中。
如果您不关心方差的精确度,您只需在文件上迭代一次并计算Nick D建议的数量,并在Adam Bowen的评论中提供详细信息。
答案 6 :(得分:0)
你有两个解决方案
从迭代器中创建一个列表并根据需要循环它。缺点是内存中的所有内容,因此如果您的文件很大,则不适用。简单地使用itertools.tee也不会救你
没有其他解决方案,除非,您不需要将get_mean的输出传递给get_sigma,因为在这种情况下它们只能是连续的,但如果您删除此限制然后你可以使用线程并行运行这两个函数,并使用itertools.tee从一个
答案 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)