本文概述
相关系数可量化数据集变量或特征之间的关联。这些统计信息对于科学技术至关重要, Python提供了许多可用于计算它们的强大工具。 SciPy, NumPy和Pandas相关方法是快速, 全面且有据可查的。
在本教程中, 你将学习:
- 皮尔逊, 斯皮尔曼和肯德尔的相关系数是多少
- 如何使用SciPy, NumPy和Pandas相关函数
- 如何使用Matplotlib可视化数据, 回归线和相关矩阵
首先, 你将对相关性进行解释, 然后看三个快速的入门示例, 最后深入了解NumPy, SciPy和Pandas相关性的细节。
免费红利:单击此处可获得免费的NumPy资源指南, 该指南为你提供了有关提高NumPy技能的最佳教程, 视频和书籍。
移除广告
相关性
统计和数据科学通常关注数据集的两个或多个变量(或特征)之间的关系。数据集中的每个数据点都是一个观测值, 特征是这些观测值的属性或属性。
你使用的每个数据集都使用变量和观察值。例如, 你可能对了解以下内容感兴趣:
- 篮球运动员的身高与他们的投篮准确性如何相关
- 员工的工作经验和工资之间是否有关系
- 不同国家的人口密度与国内生产总值之间存在什么数学上的依存关系
在上面的示例中, 身高, 射击准确性, 经验, 工资, 人口密度和国内生产总值是特征或变量。与每个参与者, 雇员和每个国家/地区有关的数据是观察值。
当数据以表的形式表示时, 该表的行通常是观测值, 而列则是要素。看一下这张雇员表:
Name | 多年经验 | 年薪 |
---|---|---|
Ann | 30 | 120, 000 |
Rob | 21 | 105, 000 |
Tom | 19 | 90, 000 |
Ivy | 10 | 82, 000 |
在此表中, 每一行代表一个观察值, 或与一个雇员(Ann, Rob, Tom或Ivy)有关的数据。每列为所有员工显示一个属性或功能(名称, 经验或薪水)。
如果你分析数据集的任意两个特征, 那么你会发现这两个特征之间存在某种类型的相关性。考虑以下数字:
这些图中的每一个都显示了三种不同的相关形式之一:
- 负相关(红色点):在左侧的图中, y值倾向于随x值的增加而减小。这显示出很强的负相关性, 当一个特征的较大值与另一个特征的较小值相对应时发生, 反之亦然。
- 相关性弱或无相关性(绿色点):中间的图没有明显的趋势。这是一种弱相关性的形式, 当两个特征之间的关联不明显或很难观察到时会发生。
- 正相关(蓝点):在右侧的图中, y值倾向于随x值的增加而增加。这说明了强正相关, 当一个特征的较大值对应于另一个特征的较大值时发生, 反之亦然。
下图表示上面的employee表中的数据:
经验与薪水之间的相关性为正, 因为更高的经验对应更高的薪水, 反之亦然。
注意:在分析相关性时, 应始终记住, 相关性并不表示因果关系。它可以量化数据集要素之间关系的强度。有时, 关联是由感兴趣的多个特征共有的因素引起的。
相关与其他统计量紧密相关, 例如平均值, 标准差, 方差和协方差。如果你想了解更多有关这些数量以及如何使用Python计算它们的信息, 请查看使用Python的描述性统计信息。
你可以使用几种统计数据来量化相关性。在本教程中, 你将了解三个相关系数:
- 皮尔逊的
- Spearman的rho
- 肯德尔的知识
皮尔森系数用于衡量线性相关性, 而斯皮尔曼系数和肯德尔系数则用于比较数据等级。有几种NumPy, SciPy和Pandas相关函数和方法可用于计算这些系数。你还可以使用Matplotlib方便地说明结果。
移除广告
示例:NumPy相关计算
NumPy有许多统计例程, 包括np.corrcoef(), 可返回Pearson相关系数矩阵。你可以从导入NumPy并定义两个NumPy数组开始。这些是ndarray类的实例。称它们为x和y:
>>>
>>> import numpy as np
>>> x = np.arange(10, 20)
>>> x
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> y = np.array([2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
>>> y
array([ 2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
在这里, 你可以使用np.arange()创建介于10(含)和20(不含)之间的整数数组x。然后, 使用np.array()创建包含任意整数的第二个数组y。
一旦拥有两个长度相同的数组, 就可以使用两个数组作为参数调用np.corrcoef():
>>>
>>> r = np.corrcoef(x, y)
>>> r
array([[1. , 0.75864029], [0.75864029, 1. ]])
>>> r[0, 1]
0.7586402890911867
>>> r[1, 0]
0.7586402890911869
corrcoef()返回相关矩阵, 该矩阵是具有相关系数的二维数组。这是你刚创建的相关矩阵的简化版本:
x y
x 1.00 0.76
y 0.76 1.00
相关矩阵的主对角线上的值(左上方和右下方)等于1。左上方的值对应于x和x的相关系数, 而右下方的值对应于y和y的相关系数。它们始终等于1。
但是, 通常需要的是相关矩阵的左下值和右上值。这些值相等, 并且都表示x和y的皮尔逊相关系数。在这种情况下, 大约为0.76。
该图显示了以上示例的数据点和相关系数:
红色方块是数据点。如你所见, 该图还显示了三个相关系数的值。
示例:SciPy相关计算
SciPy在scipy.stats中也包含许多统计例程。你可以使用以下方法来计算你先前看到的三个相关系数:
- pearsonr()
- spearmanr()
- kendalltau()
在Python中使用这些功能的方法如下:
>>>
>>> import numpy as np
>>> import scipy.stats
>>> x = np.arange(10, 20)
>>> y = np.array([2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
>>> scipy.stats.pearsonr(x, y) # Pearson's r
(0.7586402890911869, 0.010964341301680832)
>>> scipy.stats.spearmanr(x, y) # Spearman's rho
SpearmanrResult(correlation=0.9757575757575757, pvalue=1.4675461874042197e-06)
>>> scipy.stats.kendalltau(x, y) # Kendall's tau
KendalltauResult(correlation=0.911111111111111, pvalue=2.9761904761904762e-05)
请注意, 这些函数返回包含两个值的对象:
- 相关系数
- p值
测试假设时, 你可以在统计方法中使用p值。 p值是一项重要指标, 需要深入了解概率和统计数据才能进行解释。要了解有关它们的更多信息, 你可以阅读基础知识或查看数据科学家对p值的解释。
你可以将p值和相关系数及其索引提取为元组项:
>>>
>>> scipy.stats.pearsonr(x, y)[0] # Pearson's r
0.7586402890911869
>>> scipy.stats.spearmanr(x, y)[0] # Spearman's rho
0.9757575757575757
>>> scipy.stats.kendalltau(x, y)[0] # Kendall's tau
0.911111111111111
你还可以对Spearman和Kendall系数使用点表示法:
>>>
>>> scipy.stats.spearmanr(x, y).correlation # Spearman's rho
0.9757575757575757
>>> scipy.stats.kendalltau(x, y).correlation # Kendall's tau
0.911111111111111
点表示法虽然更长, 但也更具可读性和解释性。
如果要同时获得皮尔逊相关系数和p值, 则可以解压缩返回值:
>>>
>>> r, p = scipy.stats.pearsonr(x, y)
>>> r
0.7586402890911869
>>> p
0.010964341301680829
这种方法利用了Python的解压缩功能, 并利用了pearsonr()返回具有这两个统计信息的元组的事实。你也可以将这种技术与spearmanr()和kendalltau()结合使用, 稍后将对此进行介绍。
移除广告
示例:熊猫相关性计算
在某些情况下, Pandas在计算统计信息方面比NumPy和SciPy更方便。它提供了Series和DataFrame实例的统计方法。例如, 给定两个具有相同项目数的Series对象, 你可以在其中一个对象上调用.corr(), 而另一个作为第一个参数:
>>>
>>> import pandas as pd
>>> x = pd.Series(range(10, 20))
>>> x
0 10
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
dtype: int64
>>> y = pd.Series([2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
>>> y
0 2
1 1
2 4
3 5
4 8
5 12
6 18
7 25
8 96
9 48
dtype: int64
>>> x.corr(y) # Pearson's r
0.7586402890911867
>>> y.corr(x)
0.7586402890911869
>>> x.corr(y, method='spearman') # Spearman's rho
0.9757575757575757
>>> x.corr(y, method='kendall') # Kendall's tau
0.911111111111111
在这里, 你使用.corr()来计算所有三个相关系数。你可以使用参数方法定义所需的统计信息, 该方法可以采用以下几个值之一:
- “皮尔逊”
- “矛兵”
- ‘肯德尔’
- 可赎回
可调用对象可以是带有.__ call __()的任何函数, 方法或对象, 该函数可以接受两个一维数组并返回浮点数。
线性相关
线性相关性测量变量或数据集特征之间的数学关系与线性函数的接近度。如果两个特征之间的关系更接近某个线性函数, 则它们的线性相关性会更强, 并且相关系数的绝对值会更高。
皮尔逊相关系数
考虑具有两个特征的数据集:x和y。每个要素都有n个值, 因此x和y是n个元组。假设x的第一个值x 1对应于y的第一个值y 1, x的第二个值x 2对应于y的第二个值y 2, 依此类推。然后, 有n对对应的值:(x 1, y 1), (x 2, y 2), 依此类推。这些x-y对中的每对代表一个观察值。
皮尔逊(乘积矩)相关系数是两个特征之间线性关系的度量。它是x和y的协方差与其标准偏差乘积的比率。通常用字母r表示, 称为Pearson的r。你可以使用以下公式以数学方式表达此值:
r =Σᵢ((xᵢ-均值(x))(yᵢ-均值(y)))(√Σᵢ(xᵢ-均值(x))²√Σᵢ(yᵢ-均值(y))²)⁻¹
在此, i取值为1, 2, …, n。 x和y的平均值分别用mean(x)和mean(y)表示。该公式表明, 如果较大的x值倾向于对应于较大的y值, 反之亦然, 则r为正。另一方面, 如果较大的x值主要与较小的y值相关, 反之亦然, 则r为负。
以下是有关Pearson相关系数的一些重要事实:
- 皮尔逊相关系数可以采用-1≤r≤1范围内的任何实数值。
- 最大值r = 1对应于x和y之间存在理想的正线性关系的情况。换句话说, 较大的x值对应于较大的y值, 反之亦然。
- r> 0表示x和y之间呈正相关。
- 值r = 0对应于x和y独立的情况。
- 值r <0表示x和y之间的负相关。
- 最小值r = -1对应于x和y之间存在理想的负线性关系的情况。换句话说, 较大的x值对应于较小的y值, 反之亦然。
上面的事实可以总结在下表中:
皮尔逊的价值 | x和y之间的相关性 |
---|---|
等于1 | 完美的正线性关系 |
大于0 | 正相关 |
等于0 | independent |
小于0 | 负相关性 |
等于-1 | 完美的负线性关系 |
简而言之, r的绝对值越大, 相关性越强, 接近线性函数。 r的绝对值越小, 则相关性越弱。
线性回归:科学实现
线性回归是找到与要素之间的实际关系尽可能接近的线性函数的过程。换句话说, 你确定最能描述要素之间关联的线性函数。该线性函数也称为回归线。
你可以使用SciPy实现线性回归。你将获得最近似两个数组之间关系的线性函数以及Pearson相关系数。首先, 你首先需要导入库并准备一些数据以供使用:
>>>
>>> import numpy as np
>>> import scipy.stats
>>> x = np.arange(10, 20)
>>> y = np.array([2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
在这里, 你导入numpy和scipy.stats并定义变量x和y。
你可以使用scipy.stats.linregress()对长度相同的两个数组执行线性回归。你应该提供数组作为参数, 并使用点表示法获取输出:
>>>
>>> result = scipy.stats.linregress(x, y)
>>> result.slope
7.4363636363636365
>>> result.intercept
-85.92727272727274
>>> result.rvalue
0.7586402890911869
>>> result.pvalue
0.010964341301680825
>>> result.stderr
2.257878767543913
而已!你已经完成了线性回归并获得了以下结果:
。坡
:
回归线的斜率
。截距
:
回归线的截距
.pvalue
:
p值
.stderr
:
的
估计梯度的标准误差
你将在后面的部分中学习如何可视化这些结果。
你还可以为linregress()提供一个参数, 但它必须是一维数组, 其一维长度为2:
>>>
>>> xy = np.array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ... [2, 1, 4, 5, 8, 12, 18, 25, 96, 48]])
>>> scipy.stats.linregress(xy)
LinregressResult(slope=7.4363636363636365, intercept=-85.92727272727274, rvalue=0.7586402890911869, pvalue=0.010964341301680825, stderr=2.257878767543913)
结果与前面的示例完全相同, 因为xy一起包含与x和y相同的数据。 linregress()将xy的第一行作为一个功能, 将第二行作为另一个功能。
注意:在上面的示例中, scipy.stats.linregress()将行视为要素, 将列视为观察值。那是因为有两行。
机器学习中的常规做法则相反:行是观察值, 列是要素。许多机器学习库(例如Pandas, Scikit-Learn, Keras等)都遵循此约定。
在分析数据集中的相关性时, 请务必注意如何指示观察值和特征。
如果你提供xy的转置, 或者提供具有10行两列的NumPy数组, 则linregress()将返回相同的结果。在NumPy中, 你可以通过多种方式转置矩阵:
- transpose()
- .transpose()
- .T
你可以按照以下方式对xy进行转置:
>>>
>>> xy.T
array([[10, 2], [11, 1], [12, 4], [13, 5], [14, 8], [15, 12], [16, 18], [17, 25], [18, 96], [19, 48]])
现在你知道如何获取转置, 可以将其传递给linregress()。第一列将是一个功能, 第二列将是另一个功能:
>>>
>>> scipy.stats.linregress(xy.T)
LinregressResult(slope=7.4363636363636365, intercept=-85.92727272727274, rvalue=0.7586402890911869, pvalue=0.010964341301680825, stderr=2.257878767543913)
在这里, 你使用.T来获取xy的转置。 linregress()与xy及其转置的工作方式相同。它通过沿长度为2的维拆分数组来提取特征。
你还应该小心注意数据集是否包含缺失值。在数据科学和机器学习中, 你经常会发现一些丢失或损坏的数据。在Python, NumPy, SciPy和Pandas中表示它的通常方法是使用NaN或Not a Number值。但是, 如果你的数据包含nan值, 则linregress()不会得到有用的结果:
>>>
>>> scipy.stats.linregress(np.arange(3), np.array([2, np.nan, 5]))
LinregressResult(slope=nan, intercept=nan, rvalue=nan, pvalue=nan, stderr=nan)
在这种情况下, 结果对象将返回所有nan值。在Python中, nan是一个特殊的浮点值, 你可以使用以下任意一种方法获得:
- 浮点(‘nan’)
- 数学南
- numpy.nan
你还可以使用math.isnan()或numpy.isnan()检查变量是否对应于nan。
移除广告
皮尔逊相关:NumPy和SciPy实现
你已经了解了如何通过corrcoef()和pearsonr()获得皮尔逊相关系数:
>>>
>>> r, p = scipy.stats.pearsonr(x, y)
>>> r
0.7586402890911869
>>> p
0.010964341301680829
>>> np.corrcoef(x, y)
array([[1. , 0.75864029], [0.75864029, 1. ]])
请注意, 如果你为pearsonr()提供一个具有nan值的数组, 则会出现ValueError。
几乎没有其他值得考虑的细节。首先, 回想一下np.corrcoef()可以将两个NumPy数组作为参数。相反, 你可以传递具有与参数相同值的单个二维数组:
>>>
>>> np.corrcoef(xy)
array([[1. , 0.75864029], [0.75864029, 1. ]])
在此示例中, 结果与之前的示例相同。同样, xy的第一行代表一个特征, 而第二行代表另一个特征。
如果要获取三个特征的相关系数, 则只需提供一个包含三行作为参数的数字二维数组:
>>>
>>> xyz = np.array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ... [2, 1, 4, 5, 8, 12, 18, 25, 96, 48], ... [5, 3, 2, 1, 0, -2, -8, -11, -15, -16]])
>>> np.corrcoef(xyz)
array([[ 1. , 0.75864029, -0.96807242], [ 0.75864029, 1. , -0.83407922], [-0.96807242, -0.83407922, 1. ]])
你将再次获得相关矩阵, 但是该矩阵将比以前的矩阵大:
x y z
x 1.00 0.76 -0.97
y 0.76 1.00 -0.83
z -0.97 -0.83 1.00
这是因为corrcoef()将xyz的每一行都视为一个功能。值0.76是xyz的前两个特征的相关系数。这与前面示例中x和y的系数相同。 -0.97代表皮尔逊的第一个和第三个功能, 而-0.83代表皮尔逊的后两个功能。
这是一个有趣的示例, 说明当你将nan数据传递给corrcoef()时会发生什么:
>>>
>>> arr_with_nan = np.array([[0, 1, 2, 3], ... [2, 4, 1, 8], ... [2, 5, np.nan, 2]])
>>> np.corrcoef(arr_with_nan)
array([[1. , 0.62554324, nan], [0.62554324, 1. , nan], [ nan, nan, nan]])
在此示例中, arr_with_nan的前两行(或要素)都可以, 但是第三行[2, 5, np.nan, 2]包含一个nan值。不包含nan功能的所有内容都可以正确计算。但是, 取决于最后一行的结果是nan。
默认情况下, numpy.corrcoef()将行视为要素, 将列视为观察值。如果要在机器学习中广泛使用相反的行为, 请使用参数rowvar = False:
>>>
>>> xyz.T
array([[ 10, 2, 5], [ 11, 1, 3], [ 12, 4, 2], [ 13, 5, 1], [ 14, 8, 0], [ 15, 12, -2], [ 16, 18, -8], [ 17, 25, -11], [ 18, 96, -15], [ 19, 48, -16]])
>>> np.corrcoef(xyz.T, rowvar=False)
array([[ 1. , 0.75864029, -0.96807242], [ 0.75864029, 1. , -0.83407922], [-0.96807242, -0.83407922, 1. ]])
该数组与你之前看到的数组相同。在这里, 你应用了不同的约定, 但是结果是相同的。
皮尔逊相关性:熊猫实施
到目前为止, 你已经使用Series和DataFrame对象方法来计算相关系数。让我们更详细地探讨这些方法。首先, 你需要导入Pandas并创建Series和DataFrame的一些实例:
>>>
>>> import pandas as pd
>>> x = pd.Series(range(10, 20))
>>> x
0 10
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
dtype: int64
>>> y = pd.Series([2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
>>> y
0 2
1 1
2 4
3 5
4 8
5 12
6 18
7 25
8 96
9 48
dtype: int64
>>> z = pd.Series([5, 3, 2, 1, 0, -2, -8, -11, -15, -16])
>>> z
0 5
1 3
2 2
3 1
4 0
5 -2
6 -8
7 -11
8 -15
9 -16
dtype: int64
>>> xy = pd.DataFrame({'x-values': x, 'y-values': y})
>>> xy
x-values y-values
0 10 2
1 11 1
2 12 4
3 13 5
4 14 8
5 15 12
6 16 18
7 17 25
8 18 96
9 19 48
>>> xyz = pd.DataFrame({'x-values': x, 'y-values': y, 'z-values': z})
>>> xyz
x-values y-values z-values
0 10 2 5
1 11 1 3
2 12 4 2
3 13 5 1
4 14 8 0
5 15 12 -2
6 16 18 -8
7 17 25 -11
8 18 96 -15
9 19 48 -16
现在, 你有了三个名为x, y和z的Series对象。你还有两个DataFrame对象, xy和xyz。
注意:使用DataFrame实例时, 应注意, 行是观察值, 列是要素。这与机器学习中的常规做法一致。
你已经学习了如何将.corr()与Series对象一起使用以获取Pearson相关系数:
>>>
>>> x.corr(y)
0.7586402890911867
在这里, 你在一个对象上调用.corr(), 并将另一个作为第一个参数传递。
如果提供nan值, 则.corr()仍将起作用, 但它将排除包含nan值的观察值:
>>>
>>> u, u_with_nan = pd.Series([1, 2, 3]), pd.Series([1, 2, np.nan, 3])
>>> v, w = pd.Series([1, 4, 8]), pd.Series([1, 4, 154, 8])
>>> u.corr(v)
0.9966158955401239
>>> u_with_nan.corr(w)
0.9966158955401239
在这两个示例中, 你将获得相同的相关系数值。这是因为.corr()会忽略缺少值的一对值(np.nan, 154)。
你还可以将.corr()与DataFrame对象一起使用。你可以使用它来获取其列的相关矩阵:
>>>
>>> corr_matrix = xy.corr()
>>> corr_matrix
x-values y-values
x-values 1.00000 0.75864
y-values 0.75864 1.00000
所得的相关矩阵是DataFrame的新实例, 并保存xy [‘x-values’]和xy [‘y-values’]列的相关系数。这样标记的结果通常很方便使用, 因为你可以使用它们的标签或整数位置索引来访问它们:
>>>
>>> corr_matrix.at['x-values', 'y-values']
0.7586402890911869
>>> corr_matrix.iat[0, 1]
0.7586402890911869
此示例显示了两种访问值的方法:
- 使用.at []通过行和列标签访问单个值。
- 使用.iat []通过值的行和列的位置来访问值。
可以对包含三列或更多列的DataFrame对象以相同的方式应用.corr():
>>>
>>> xyz.corr()
x-values y-values z-values
x-values 1.000000 0.758640 -0.968072
y-values 0.758640 1.000000 -0.834079
z-values -0.968072 -0.834079 1.000000
你将获得具有以下相关系数的相关矩阵:
- x值和y值0.758640
- x值和z值-0.968072
- y值和z值-0.834079
另一个有用的方法是.corrwith(), 它使你可以计算一个DataFrame对象与另一个作为第一个参数传递的Series或DataFrame对象的行或列之间的相关系数:
>>>
>>> xy.corrwith(z)
x-values -0.968072
y-values -0.834079
dtype: float64
在这种情况下, 结果是一个新的Series对象, 该对象具有xy [‘x-values’]列和z值的相关系数, 以及xy [‘y-values’]和z的系数。
.corrwith()具有可选的参数轴, 该参数轴指定列还是行代表要素。 axis的默认值为0, 并且还默认为表示要素的列。还有一个drop参数, 该参数指示如何处理缺少的值。
.corr()和.corrwith()都具有可选参数方法, 以指定要计算的相关系数。默认情况下会返回Pearson相关系数, 因此在这种情况下你无需提供该系数。
移除广告
等级相关
等级相关性比较与两个变量或数据集特征相关的数据的等级或顺序。如果顺序相似, 则相关性强, 正且高。但是, 如果顺序接近颠倒, 则相关性很强, 为负且很低。换句话说, 等级相关仅与值的顺序有关, 而与数据集中的特定值无关。
为了说明线性和秩相关之间的区别, 请考虑下图:
左边的图在x和y之间具有理想的正线性关系, 因此r =1。中间的图显示正相关, 右边的图显示负相关。但是, 它们都不是线性函数, 因此r不同于-1或1。
当你仅查看顺序或等级时, 所有三个关系都是完美的!左图和中央图显示了观察值, 其中较大的x值始终对应于较大的y值。这是完美的正秩相关。右图说明了相反的情况, 这是完美的负秩相关。
斯皮尔曼相关系数
两个特征之间的Spearman相关系数是它们的等级值之间的Pearson相关系数。它的计算方法与Pearson相关系数相同, 但是考虑了其排名而不是其值。通常用希腊字母rh(ρ)表示, 也称为Spearman的rho。
假设你有两个n元组, x和y, 其中(x₁, y, ), (x_2, y_2), …是成对的观察值。你可以按照与皮尔森系数相同的方式计算斯皮尔曼相关系数ρ。你将使用等级, 而不是x和y的实际值。
以下是有关Pearson相关系数的一些重要事实:
- 它可以取-1≤ρ≤1范围内的实数值。
- 其最大值ρ= 1对应于x和y之间存在单调递增函数的情况。换句话说, 较大的x值对应于较大的y值, 反之亦然。
- 其最小值ρ= -1对应于x和y之间存在单调递减函数的情况。换句话说, 较大的x值对应于较小的y值, 反之亦然。
你可以使用与Pearson的r非常相似的方式在Python中计算Spearman的rho。
肯德尔相关系数
让我们从考虑两个n元组x和y开始。每个x-y对(x 1, y 1), (x 2, y 2), …是单个观察值。一对观测值(xᵢ, yᵢ)和(xⱼ, yⱼ), 其中i <j, 将是以下三种情况之一:
- 符合(xᵢ>xⱼ和yᵢ>yⱼ)或(xᵢ<xⱼ和yᵢ<yⱼ)
- (xᵢ<xⱼ和yᵢ>yⱼ)或(xᵢ>xⱼ和yᵢ<yⱼ)不一致
- 如果x(xᵢ=xⱼ)或y(yᵢ=yⱼ)没有关系
肯德尔相关系数比较一致和不一致数据对的数量。该系数基于一致和不一致对的计数相对于x-y对的数量的差异。通常用希腊字母tau(τ)表示, 并称为Kendall的tau。
根据scipy.stats官方文档, 肯德尔相关系数的计算公式为τ=(n⁺-n⁻)/√((n⁺+n⁻+nˣ)(n⁺+n⁻+nʸ)), 其中:
- n⁺是一致对的数量
- n⁻是不和谐对的数量
- nˣ是仅x中的联系数
- nʸ是仅在y中的联系数
如果x和y都出现平局, 则nˣ或nʸ均不包含平局。
肯德尔等级相关系数的维基百科页面给出以下表达式:对于i <j, τ=(2 /(n(n-1)))Σᵢⱼ(sign(xᵢ-xⱼ)sign(yᵢ-yⱼ)), 其中i = 1, 2, …, n − 1并且j = 2, 3, …, n。如果z <0, 则符号函数sign(z)为-1, 如果z = 0, 则为0, 如果z> 0, 则为1。n(n-1)/ 2是x-y对的总数。
有关肯德尔相关系数的一些重要事实如下:
- 它可以取−1≤τ≤1范围内的实数值。
- 其最大值τ= 1对应于x和y中相应值的等级相同的情况。换句话说, 所有对都是一致的。
- 其最小值τ= -1对应于x的排名与y的排名相反的情况。换句话说, 所有对都是不一致的。
你可以使用Python计算Kendall的tau, 方法与计算Pearson的r相似。
移除广告
排名:科学实施
你可以使用scipy.stats确定数组中每个值的等级。首先, 你将导入库并创建NumPy数组:
>>>
>>> import numpy as np
>>> import scipy.stats
>>> x = np.arange(10, 20)
>>> y = np.array([2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
>>> z = np.array([5, 3, 2, 1, 0, -2, -8, -11, -15, -16])
准备好数据后, 你可以使用scipy.stats.rankdata()确定NumPy数组中每个值的排名:
>>>
>>> scipy.stats.rankdata(x)
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
>>> scipy.stats.rankdata(y)
array([ 2., 1., 3., 4., 5., 6., 7., 8., 10., 9.])
>>> scipy.stats.rankdata(z)
array([10., 9., 8., 7., 6., 5., 4., 3., 2., 1.])
数组x和z是单调的, 因此它们的秩也是单调的。 y中的最小值是1, 它对应于等级1。第二个最小值是2, 对应于等级2。最大值是96, 其对应于最大等级10, 因为数组中有10个项目。
rankdata()具有可选的参数方法。这告诉Python如果数组中有联系(如果两个或多个值相等)该怎么办。默认情况下, 它将为他们分配平均排名:
>>>
>>> scipy.stats.rankdata([8, 2, 0, 2])
array([4. , 2.5, 1. , 2.5])
有两个值为2的元素, 它们的排名分别为2.0和3.0。值0的等级为1.0, 值8的等级为4.0。然后, 两个值为2的元素将获得相同的等级2.5。
rankdata()将nan值当作大值对待:
>>>
>>> scipy.stats.rankdata([8, np.nan, 0, 2])
array([3., 4., 1., 2.])
在这种情况下, 值np.nan对应于最大等级4.0。你还可以使用np.argsort()获得排名:
>>>
>>> np.argsort(y) + 1
array([ 2, 1, 3, 4, 5, 6, 7, 8, 10, 9])
argsort()返回数组项在已排序数组中的索引。这些索引从零开始, 因此你需要将所有索引加1。
等级相关:NumPy和SciPy实施
你可以使用scipy.stats.spearmanr()计算Spearman相关系数:
>>>
>>> result = scipy.stats.spearmanr(x, y)
>>> result
SpearmanrResult(correlation=0.9757575757575757, pvalue=1.4675461874042197e-06)
>>> result.correlation
0.9757575757575757
>>> result.pvalue
1.4675461874042197e-06
>>> rho, p = scipy.stats.spearmanr(x, y)
>>> rho
0.9757575757575757
>>> p
1.4675461874042197e-06
spearmanr()返回一个对象, 其中包含Spearman相关系数的值和p值。如你所见, 你可以通过两种方式访问特定值:
- Using dot notation (result.correlation and result.pvalue)
- 使用Python解压缩(rho, p = scipy.stats.spearmanr(x, y))
如果向spearmanr()提供包含与x和y相同数据的二维数组xy, 则可以获得相同的结果:
>>>
>>> xy = np.array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ... [2, 1, 4, 5, 8, 12, 18, 25, 96, 48]])
>>> rho, p = scipy.stats.spearmanr(xy, axis=1)
>>> rho
0.9757575757575757
>>> p
1.4675461874042197e-06
xy的第一行是一个特征, 而第二行是另一个特征。你可以修改它。可选参数axis确定列(轴= 0)还是行(轴= 1)代表要素。默认行为是, 行是观察值, 列是要素。
另一个可选参数nan_policy定义如何处理nan值。它可以采用以下三个值之一:
- 如果输入中存在nan值, 则“ propagate”将返回nan。这是默认行为。
- 如果输入中存在nan值, 则“ raise”会引发ValueError。
- “忽略”忽略具有nan值的观察值。
如果你提供的二维数组具有两个以上的特征, 那么你将获得相关矩阵和p值矩阵:
>>>
>>> xyz = np.array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ... [2, 1, 4, 5, 8, 12, 18, 25, 96, 48], ... [5, 3, 2, 1, 0, -2, -8, -11, -15, -16]])
>>> corr_matrix, p_matrix = scipy.stats.spearmanr(xyz, axis=1)
>>> corr_matrix
array([[ 1. , 0.97575758, -1. ], [ 0.97575758, 1. , -0.97575758], [-1. , -0.97575758, 1. ]])
>>> p_matrix
array([[6.64689742e-64, 1.46754619e-06, 6.64689742e-64], [1.46754619e-06, 6.64689742e-64, 1.46754619e-06], [6.64689742e-64, 1.46754619e-06, 6.64689742e-64]])
相关矩阵中的值-1表明第一特征和第三特征具有完美的负秩相关, 也就是说, 第一行中的较大值始终对应于第三行中的较小值。
你可以使用kendalltau()获得肯德尔相关系数:
>>>
>>> result = scipy.stats.kendalltau(x, y)
>>> result
KendalltauResult(correlation=0.911111111111111, pvalue=2.9761904761904762e-05)
>>> result.correlation
0.911111111111111
>>> result.pvalue
2.9761904761904762e-05
>>> tau, p = scipy.stats.kendalltau(x, y)
>>> tau
0.911111111111111
>>> p
2.9761904761904762e-05
kendalltau()的工作方式与spearmanr()类似。它采用两个一维数组, 具有可选参数nan_policy, 并返回具有相关系数和p值的对象。
但是, 如果仅提供一个二维数组作为参数, 则kendalltau()将引发TypeError。如果你传递两个形状相同的多维数组, 则在计算之前将它们展平。
移除广告
排名相关:熊猫实施
你可以使用Pandas计算Spearman和Kendall相关系数。与之前一样, 你首先要导入熊猫并创建一些Series和DataFrame实例:
>>>
>>> import pandas as pd
>>> x, y, z = pd.Series(x), pd.Series(y), pd.Series(z)
>>> xy = pd.DataFrame({'x-values': x, 'y-values': y})
>>> xyz = pd.DataFrame({'x-values': x, 'y-values': y, 'z-values': z})
现在有了这些Pandas对象, 就可以像计算Pearson相关系数时一样使用.corr()和.corrwith()了。你只需要使用可选参数方法(默认为’pearson’)指定所需的相关系数即可。
要计算Spearman的rho, 请通过method = spearman:
>>>
>>> x.corr(y, method='spearman')
0.9757575757575757
>>> xy.corr(method='spearman')
x-values y-values
x-values 1.000000 0.975758
y-values 0.975758 1.000000
>>> xyz.corr(method='spearman')
x-values y-values z-values
x-values 1.000000 0.975758 -1.000000
y-values 0.975758 1.000000 -0.975758
z-values -1.000000 -0.975758 1.000000
>>> xy.corrwith(z, method='spearman')
x-values -1.000000
y-values -0.975758
dtype: float64
如果你想要肯德尔的牛头, 请使用method = kendall:
>>>
>>> x.corr(y, method='kendall')
0.911111111111111
>>> xy.corr(method='kendall')
x-values y-values
x-values 1.000000 0.911111
y-values 0.911111 1.000000
>>> xyz.corr(method='kendall')
x-values y-values z-values
x-values 1.000000 0.911111 -1.000000
y-values 0.911111 1.000000 -0.911111
z-values -1.000000 -0.911111 1.000000
>>> xy.corrwith(z, method='kendall')
x-values -1.000000
y-values -0.911111
dtype: float64
如你所见, 与SciPy不同, 你可以使用单个二维数据结构(一个数据框)。
关联的可视化
数据可视化在统计和数据科学中非常重要。它可以帮助你更好地了解数据, 并更好地了解功能之间的关系。在本部分中, 你将学习如何使用x-y图表直观地表示两个要素之间的关系。你还将使用热图可视化相关矩阵。
你将学习如何准备数据并获得特定的视觉表示, 但不会涵盖其他许多解释。要深入了解有关Matplotlib的更多信息, 请查看使用Matplotlib进行Python绘图(指南)。你还可以查看Matplotlib的官方文档和解剖。
首先, 首先导入matplotlib.pyplot:
>>>
>>> import matplotlib.pyplot as plt
>>> plt.style.use('ggplot')
在这里, 你使用plt.style.use(‘ggplot’)设置绘图样式。如果需要, 请随时跳过此行。
你将使用上一部分中的数组x, y, z和xyz。你可以再次创建它们以减少滚动:
>>>
>>> import numpy as np
>>> import scipy.stats
>>> x = np.arange(10, 20)
>>> y = np.array([2, 1, 4, 5, 8, 12, 18, 25, 96, 48])
>>> z = np.array([5, 3, 2, 1, 0, -2, -8, -11, -15, -16])
>>> xyz = np.array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ... [2, 1, 4, 5, 8, 12, 18, 25, 96, 48], ... [5, 3, 2, 1, 0, -2, -8, -11, -15, -16]])
有了数据后, 就可以绘制了。
带有回归线的X-Y图
首先, 你将了解如何使用回归线, 方程式和Pearson相关系数来创建x-y图。你可以使用linregress()获得回归线的斜率和截距以及相关系数:
>>>
>>> slope, intercept, r, p, stderr = scipy.stats.linregress(x, y)
现在, 你拥有了所需的所有值。你还可以使用回归线方程和相关系数的值来获取字符串。 f字符串非常方便用于此目的:
>>>
>>> line = f'Regression line: y={intercept:.2f}+{slope:.2f}x, r={r:.2f}'
>>> line
'Regression line: y=-85.93+7.44x, r=0.76'
现在, 使用.plot()创建x-y图:
fig, ax = plt.subplots()
ax.plot(x, y, linewidth=0, marker='s', label='Data points')
ax.plot(x, intercept + slope * x, label=line)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend(facecolor='white')
plt.show()
你的输出应如下所示:
红色方块代表观测值, 蓝色线代表回归线。图例中列出了其方程式以及相关系数。
移除广告
关联矩阵的热图
当你具有许多功能时, 相关矩阵会变得非常大且令人困惑!幸运的是, 你可以将其可视化为热图, 其中每个字段的颜色都与其值相对应。你将需要相关矩阵:
>>>
>>> corr_matrix = np.corrcoef(xyz).round(decimals=2)
>>> corr_matrix
array([[ 1. , 0.76, -0.97], [ 0.76, 1. , -0.83], [-0.97, -0.83, 1. ]])
你可以方便地使用.round()将相关矩阵中的数字四舍五入, 因为它们将显示在热图上。
最后, 使用.imshow()和相关矩阵作为参数创建你的热图:
fig, ax = plt.subplots()
im = ax.imshow(corr_matrix)
im.set_clim(-1, 1)
ax.grid(False)
ax.xaxis.set(ticks=(0, 1, 2), ticklabels=('x', 'y', 'z'))
ax.yaxis.set(ticks=(0, 1, 2), ticklabels=('x', 'y', 'z'))
ax.set_ylim(2.5, -0.5)
for i in range(3):
for j in range(3):
ax.text(j, i, corr_matrix[i, j], ha='center', va='center', color='r')
cbar = ax.figure.colorbar(im, ax=ax, format='% .2f')
plt.show()
你的输出应如下所示:
结果是带有系数的表。它看起来像带有彩色背景的熊猫输出。颜色可帮助你解释输出。在此示例中, 黄色代表数字1, 绿色代表0.76, 紫色代表负数。
结论
你现在知道, 相关系数是统计数据, 用于测量变量或数据集特征之间的关联。它们在数据科学和机器学习中非常重要。
现在, 你可以使用Python计算:
- 皮尔逊的产品与时刻的相关系数
- 斯皮尔曼等级相关系数
- 肯德尔的等级相关系数
现在, 即使使用大型数据集, 你也可以使用NumPy, SciPy和Pandas相关函数和方法来有效地计算这些(和其他)统计信息。你还知道如何使用Matplotlib图和热图可视化数据, 回归线和相关矩阵。
如果你有任何问题或意见, 请将其放在下面的评论部分!