我厌倦了 scipy 和 numpy,并决定继续研究另一个实现,基于某处的 SO 答案。
from statistics import pstdev, mean
def pearson(x, y):
sx = []
sy = []
mx = mean(x)
my = mean(y)
stdx = pstdev(x)
stdy = pstdev(y)
for i in x:
sx.append((i - mx) / stdx)
for j in y:
sy.append((j - my) / stdy)
return sum([i * j for i, j in zip(sx, sy)]) / len(x)
我向其中传递了一些数字,看看它是否给出了与 scipy.stats.pearsonr 相同的结果,看起来没问题。最后的一些数字有所不同,但没有什么突破性的......
直到我尝试将相同的数据集传递给它作为x
和y
。当我这样做时,我得到了 0.9999999999999992
,而 scipy 和 numpy 都说它是 1.0
。
这个实现有问题吗?我使用的是总体标准差而不是样本标准差,据我所知,numpy 和 scipy 都使用它。我想知道为什么这没有返回应有的 1.0
。难道是python本身的 float 问题?我已经在 Py 2 和 3 中尝试过,并且在两者中都得到了 0.999...
。
如果需要,我传递给它的数据集是:
[7, 1, 5, 1, 8, 5, 9, 8, 5, 10, 5, 8, 1, 8, 8, 8, 10, 4, 8, 9, 9, 6 , 8, 7, 8, 5, 10, 5, 6, 8, 8, 7, 9, 4, 6, 10, 7, 10, 4, 5, 4, 7, 4, 8, 9, 10, 9 , 8, 7, 8, 6, 8, 6, 6, 5, 7, 7, 7, 7, 3, 7, 8, 6, 8, 5, 7, 8, 7, 8, 6, 8, 6 , 9, 6, 6, 6, 8, 9, 5, 7, 9, 2, 9, 6, 7, 6, 7, 7, 5, 5, 7, 7, 8, 6, 9, 1, 3 , 6, 7, 9, 7, 7, 6, 9, 9, 4, 9, 9, 7, 9, 6, 2, 2, 8, 4, 7, 7, 6, 3, 7, 3, 5 , 10, 9, 8, 10, 8, 7, 4, 7, 8, 9, 8, 4, 7, 9, 7, 7, 6, 8, 8, 9, 9, 7, 4, 4, 7 , 3, 9, 3, 1, 8, 3, 9, 4, 8, 3, 9, 8, 8, 7, 9, 9, 8, 10, 8, 3, 10, 4, 7, 7, 10 , 8, 7, 8, 7, 1, 8, 9, 5, 7, 5, 5, 3, 5, 7, 7, 7, 2, 4, 1, 6, 9, 9, 7, 7, 10 , 9, 2, 9, 8, 2, 5, 1, 2, 5, 9, 1, 4, 8, 9, 6, 4, 4, 7, 3, 7, 9, 4, 3, 7, 8 , 7, 6, 8, 8, 7]
最佳答案
您对浮点行为的期望过于乐观。根据经验,您不会对结果不完全是 1.0 感到惊讶。例如,尝试使用更小的输入:
[7, 1, 5]
在我的盒子上,你的函数返回 1.0000000000000002。 “接近”1.0,但不完全是1.0。一般来说,这是您所能期望的最好结果。
要了解原因,请考虑“应该”计算什么:
math.sqrt(x)**2 == x
从数学上来说(以无限精度工作),应该始终返回 True。但在浮点中(无论使用多少精度,只要精度有界),它不可能总是正确的。事实上,反例很容易找到;就像刚才在我的盒子上一样:
>>> math.sqrt(2)**2
2.0000000000000004
问题是,在有限精度下,sqrt()
必然是一个多对一函数。它将域 1..N
压缩到范围 1..sqrt(N)
中,并且在有限精度下,域的基数大于该范围的基数。因此,域中必须存在不同的 x
和 y
映射到范围内的相同值,因此不存在精确的函数逆。
您的函数比普通的 sqrt
更复杂,但工作原理相同。
关于python - 当向其传递两组相同的数据时,自制的 pearson 相关实现返回 0.999...2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44573450/