当常量列表传递给
corrcoef
函数时,numpy
中的 corrcoef()
似乎会抛出 RuntimeWarning,例如下面的代码会抛出警告:
import numpy as np
X = [1.0, 2.0, 3.0, 4.0]
Y = [2, 2, 2, 2]
print(np.corrcoef(X, Y)[0, 1])
警告:
/usr/local/lib/python3.6/site-packages/numpy/lib/function_base.py:3003: RuntimeWarning: invalid value encountered in true_divide
c /= stddev[:, None]
任何人都可以解释为什么当其中一个列表是常量时会抛出此错误,以及当常量列表传递给函数时如何防止此错误?
相关性是衡量两个向量变化时相互追踪程度的指标。当一个向量不改变时,你无法追踪相互的变化。
正如OP评论中所指出的,皮尔逊乘积矩相关系数的公式将
X
和Y
的协方差除以它们标准差的乘积。由于 Y
在您的示例中方差为零,因此其标准差也为零。这就是为什么你会得到 true_divide
错误 - 你试图除以零。
注意:从工程的角度来看,简单地将一个非常小的数量(例如,略高于机器 epsilon 的值)添加到
Y
中的条目之一似乎很诱人,以解决零除问题。但这在统计上是不可行的。即使添加 1e-15
也会严重扰乱您的相关系数,具体取决于您将其添加到哪个值。
考虑这两种情况之间的区别:
X = [1.0, 2.0, 3.0, 4.0]
tiny = 1e-15
# add tiny amount to second element
Y1 = [2., 2.+tiny, 2., 2.]
np.corrcoef(X, Y1)[0, 1]
-0.22360679775
# add tiny amount to fourth element
Y2 = [2., 2., 2., 2.+tiny]
np.corrcoef(X, Y2)[0, 1]
0.67082039325
这对统计学家来说可能是显而易见的,但考虑到问题的性质,这似乎是一个相关的警告。
Pandas .corr 在这种情况下甚至存在 NaN 时更加通用,因此第一个选择可能是将列表转换为 pandas 系列并使用 pandas 相关性,响应将是 nan;
import pandas as pd
X = [1.0, 2.0, 3.0, 4.0]
Y = [2, 2, 2, 2]
print(pd.Series(X).corr( pd.Series(Y)))
如果你想坚持使用 numpy 那么你可以使用 if 语句检查序列的标准差,并仅当它们大于零时才继续进行相关。显然这里我们没有有效的输出,因为一个列表没有变化,但这个概念可以应用于其他情况。
import numpy as np
X = [1.0, 2.0, 3.0, 4.0]
Y = [2, 2, 2, 2]
if np.std(Y)==0 or np.std(X)==0 :
print ('The correlation could not be computed because the standard deviation of one of the series is equal to zero')
else:
print(np.corrcoef(X, Y)[0, 1])
这是
np.corrcoef
的“固定”版本:
def pearsonccs(samples):
C = np.cov(samples)
diag = np.diag(C)
N = np.sqrt(np.outer(diag, diag))
N[N == 0] = 1
return C / N
它所做的只是将协方差矩阵中的零替换为 1,以避免被零除错误。