作为一个更大的项目的一部分,我正在编写一个函数,它接受一个intt的字典,并返回一个字典,每个"外部"密钥链接到该子字典的平均值和标准偏差的元组(即(mean(dict[key1]), stdev(dict[key1]))
)。我正在操作一个大型数据集(源文件是一个2.8 GB的csv文件),并在计算其中一个子字节的标准偏差时得到一个断言错误。
虽然我(并且目前正在)追踪导致下面错误的子字典,但我很好奇一般情况可能导致它如此,所以如果它进一步发生在我的数据集中,我可以尝试避免它。
我收到的错误消息是:
AssertionError: negative sum of square deviations: -3734262324235.697754
来自代码:
import statistics as stat
try: #Check for single value error
std = stat.stdev(val)
except stat.StatisticsError:
std = 0
答案 0 :(得分:2)
statiscs.py
中的代码是纯Python - 在处理内部" quares之和statistics._ss
函数时,您似乎是Fraction类中奇怪的溢出错误的受害者。
我认为你现在可以做的最好的事情就是使用" if"来构建_ss
文件本身中的statistics.py
函数。并调用pdb.set_trace
以交互方式查找导致错误的数据(代码中有一条注释,表明此部分存在舍入错误)。它计算一个shuld为零的分数 - 但是对于舍入误差,以及该分数的平方。但是在平方时,已经很大的分母本身就是平方 - 这可能会引发Python的Fraction中的一个错误,并且当它应该接近于零时返回一个非常大的值。
这样的"如果"子句可以允许您(1)绕过错误条件并将代码运行到最后,在找到错误时强制该值为零; (2)记下导致错误的值,并将其报告为Python语言本身的错误。
答案 1 :(得分:0)
这是@jsbueno提到的statistics.py
文件问题。我也遇到了同样的错误,并通过将statistics.stdev
替换为numpy.std
而不是对源代码进行更改来解决了该问题。
答案 2 :(得分:0)
我遇到了一个很小的问题。 sum(x²)的精确计算得出的结果为零(Fraction(0,1)),而sum(x)的精确计算给出了一个很小的正分数,表示取整误差和精度的损失。从数据中得出平均值。
statistics.py中的代码指示total2应该为零,但实际上可以是任何小数,正数或负数。 total2的平方始终是一个小的正分数。
def _ss(data, c=None):
"""Return sum of square deviations of sequence data.
If ``c`` is None, the mean is calculated in one pass, and the deviations
from the mean are calculated in a second pass. Otherwise, deviations are
calculated from ``c`` as given. Use the second case with care, as it can
lead to garbage results.
"""
if c is None:
c = mean(data)
T, total, count = _sum((x-c)**2 for x in data)
# The following sum should mathematically equal zero, but due to rounding
# error may not.
U, total2, count2 = _sum((x-c) for x in data)
assert T == U and count == count2
total -= total2**2/len(data)
assert not total < 0, 'negative sum of square deviations: %f' % total
return (T, total)
因此,恰恰在失败的断言之前,总方差可以变成负值。
根本原因是在第一个_sum函数调用中将每个值取平方时会发生精度损失。 float或np.float64值通过浮点运算在列表推导中平方。
一种可能的更正方法是在平方之前将total2转换为类型T。它更改了语义,因为_ss返回类型T的值而不是精确的分数。另一种更准确的方法是,在首次调用_sum之前,将x-c一次全部转换为小数。在这两种情况下,计算都将更快。
最合适的校正并非微不足道,因为_sum还会汇总来自对_coerce的连续调用的类型。较早地将数据转换为分数也将结果的类型更改为分数。