为什么内置的python sum函数的行为如此?

时间:2019-01-06 05:17:17

标签: python pearson-correlation

我正在尝试编写一个程序来确定python中具有总体标准偏差的皮尔逊相关系数。我认为在我求和(yi-μy)*(xi-μx)之前,这将是微不足道的。这是我的完整代码:

def r(x, y):
    mx, my = sum(x) / len(x), sum(y) / len(y)
    sdx, sdy = (sum([(xi-mx)**2 for xi in x]) / len(x))**0.5, (sum([(yi- 
    my)**2 for yi in y]) / (len(y)))**0.5
    res = ((sum([(xi-mx)*(yi-my) for xi in x for yi in y]))/(len(x)*sdx*sdy))**0.5
    return res

我注意到结果很小,所以我检查了(xi-mx)的总和:

sum([(xi-mx) for xi in x])

,结果为-9.769962616701378e-15。这是列表中的值:

print([(xi-mx) for xi in x])
[3.2699999999999987, 3.0699999999999994, 1.2699999999999987, 1.0699999999999985, 0.9699999999999989, 0.2699999999999987, -0.7300000000000013, -1.7300000000000013, -2.7300000000000013, -4.730000000000001]

有人能解释为什么python表现得如此奇怪吗?

2 个答案:

答案 0 :(得分:5)

res = (sum([(xi-mx)*(yi-my) for xi in x for yi in y]))/(len(x)*sdx*sdy)

那没有按照您的想法去做。在计算皮尔逊相关系数的分子时,(xi - mx) * (yi - my)应该顺序配对。 使用zip应该可以解决。

res = (sum([(xi-mx)*(yi-my) for xi, yi in zip(x, y)]))/(len(x)*sdx*sdy)

这就是我得到的:

def r(x, y):
    mx, my = sum(x) / len(x), sum(y) / len(y)
    sdx, sdy = (sum([(xi-mx)**2 for xi in x]) / len(x))**0.5, (sum([(yi-
    my)**2 for yi in y]) / (len(y)))**0.5
    res = (sum([(xi-mx)*(yi-my) for xi, yi in zip(x, y)]))/(len(x)*sdx*sdy)
    return res

r(x, y) # 0.6124721937208479

for xi in x for yi in y的真正作用是什么?

>>> x, y = [1, 2, 3], [4, 5, 6]
>>> [(xi, yi) for xi in x for yi in y]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

所以重复不断。 (实际上是生成组合列表。)您可以使用zip将值聚合成对:

>>> [*zip(x, y)]
[(1, 4), (2, 5), (3, 6)]

答案 1 :(得分:4)

您显示的数字总和实际上接近0。为什么这么奇怪?实际上,它必须接近于0。无论数学上以x开头的值是什么,

sum(xi - mean(x) for xi in x) =
sum(xi for xi in x) - sum(mean(x) for xi in x) =
len(x) * mean(x) - len(x) * mean(x) =
0

数字结果不完全为0完全是由于浮点舍入错误造成的。