我在使用 scipy.stats 中的 Spearmanr 时遇到一些奇怪的问题。我使用多项式的值来获取一些更有趣的相关性,但是如果我手动输入值(作为列表,转换为 numpy 数组),我会得到与我得到的不同的相关性如果我使用函数计算值。下面的代码应该可以说明我的意思:
import numpy as np
from scipy.stats import spearmanr
data = np.array([ 0.4, 1.2, 1. , 0.4, 0. , 0.4, 2.2, 6. , 12.4, 22. ])
axis = np.arange(0, 10, dtype=np.float64)
print(spearmanr(axis, data))# gives a correlation of 0.693...
# Use this polynomial
poly = lambda x: 0.1*(x - 3.0)**3 + 0.1*(x - 1.0)**2 - x + 3.0
data2 = poly(axis)
print(data2) # It is the same as data
print(spearmanr(axis, data2))# gives a correlation of 0.729...
我确实注意到数组略有不同(即 data - data2
并非所有元素都完全为零),但差异很小 - 顺序为 1e-16。
如此微小的差异足以让 Spearmanr 甩掉这么多吗?
Is such a tiny difference enough to throw off spearmanr by this much?
是的,因为斯 PIL 曼的r是基于样本排名的。如此微小的差异可能会改变原本相等的值的排名:
sp.stats.rankdata(data)
# array([ 3., 6., 5., 3., 1., 3., 7., 8., 9., 10.])
# Note that all three values of 0.4 get the same rank 3.
sp.stats.rankdata(data2)
# array([ 2.5, 6. , 5. , 2.5, 1. , 4. , 7. , 8. , 9. , 10. ])
# Note that two values 0.4 get the rank 2.5 and one gets 4.
如果您添加一个小梯度(大于您观察到的数值差异)来打破这种联系,您将得到相同的结果:
print(spearmanr(axis, data + np.arange(10)*1e-12))
# SpearmanrResult(correlation=0.74545454545454537, pvalue=0.013330146315440047)
print(spearmanr(axis, data2 + np.arange(10)*1e-12))
# SpearmanrResult(correlation=0.74545454545454537, pvalue=0.013330146315440047)
然而,这将打破任何可能故意的联系,并可能导致高估或低估相关性。 numpy.round
如果数据预计具有离散值,可能是更好的解决方案。
我是一名优秀的程序员,十分优秀!