相关性

本节将建立一种度量,用于衡量散点图围绕一条直线的聚集程度。在形式上,这被称为度量“线性关联”。

[In ]:
from datascience import *
%matplotlib inline
path_data = '../../../assets/data/'
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
import math
import numpy as np
from scipy import stats
[In ]:
def r_scatter(r):
    plots.figure(figsize=(5,5))
    "Generate a scatter plot with a correlation approximately r"
    x = np.random.normal(0, 1, 1000)
    z = np.random.normal(0, 1, 1000)
    y = r*x + (np.sqrt(1-r**2))*z
    plots.scatter(x, y)
    plots.xlim(-4, 4)
    plots.ylim(-4, 4)

hybrid 包含 1997 年至 2013 年在美国销售的混合动力乘用车数据。数据改编自佛罗里达大学 Prof. Larry Winner 的在线数据档案。各列含义如下:

  • vehicle:汽车型号
  • year:生产年份
  • msrp:制造商建议零售价(以 2013 年美元计)
  • acceleration:加速度(公里/小时/秒)
  • mpg:燃油效率(英里/加仑)
  • class:车型类别
[In ]:
hybrid = Table.read_table(path_data + 'hybrid.csv')
[In ]:
hybrid
vehicle         | year | msrp    | acceleration | mpg   | class
Prius (1st Gen) | 1997 | 24509.7 | 7.46         | 41.26 | Compact
Tino            | 2000 | 35355   | 8.2          | 54.1  | Compact
Prius (2nd Gen) | 2000 | 26832.2 | 7.97         | 45.23 | Compact
Insight         | 2000 | 18936.4 | 9.52         | 53    | Two Seater
Civic (1st Gen) | 2001 | 25833.4 | 7.04         | 47.04 | Compact
Insight         | 2001 | 19036.7 | 9.52         | 53    | Two Seater
Insight         | 2002 | 19137   | 9.71         | 53    | Two Seater
Alphard         | 2003 | 38084.8 | 8.33         | 40.46 | Minivan
Insight         | 2003 | 19137   | 9.52         | 53    | Two Seater
Civic           | 2003 | 14071.9 | 8.62         | 41    | Compact
... (143 rows omitted)

下图是 msrp acceleration 的散点图。这意味着 msrp 绘制在纵轴上,acceleration 绘制在横轴上。

[In ]:
hybrid.scatter('acceleration', 'msrp')
Scatterplot with 'acceleration' on the x-axis and 'msrp' on the y-axis. Generally there is a positive assocation; as the x value increases so does the y value. As the x value increases there are fewere data points and trend is a little less clear.

注意正关联。散点呈上升趋势,表明加速度较大的汽车平均价格更高;反之,价格较高的汽车平均加速度也更大。

MSRP 对里程的散点图显示负关联。里程较高的混合动力汽车平均价格较低。这似乎令人惊讶,但考虑到加速快的汽车往往燃油效率较低、里程较低,这就不足为奇了。正如之前的散点图所示,这些也是价格较高的汽车。

[In ]:
hybrid.scatter('mpg', 'msrp')
Scatterplot with 'mpg' on the x-axis and 'msrp' on the y-axis. The x-axis ranges from about x=20 to about x=70. There is a non-linear association between x and y values. On the left hand side of the graph, there appears to be a weak negative assocation, but above x=40, there is no clear association between x and y values, however the y values remain small.

除了负关联之外,价格对效率的散点图还显示出两个变量之间的非线性关系。这些点似乎聚集在一条曲线周围,而不是一条直线周围。

然而,如果我们仅将数据限制在 SUV 类别,价格与效率之间的关联仍然是负的,但关系看起来更接近线性。SUV 的价格与加速度之间的关系也呈现线性趋势,但斜率为正。

[In ]:
suv = hybrid.where('class', 'SUV')
suv.scatter('mpg', 'msrp')
Scatterplot with 'mpg' on the x-axis and 'msrp' on the y-axis. There is a clear negative association; as the x value increases, the y value decreases. 
[In ]:
suv.scatter('acceleration', 'msrp')
Scatterplot with 'acceleration' on the x-axis and 'msrp' on the y-axis. There appears to be a postive association; as x increases so does y. There are some obvious outliers.

您可能已经注意到,即使不关注变量的测量单位,我们也能从散点图的大致方向和形状中获取有用信息。

事实上,我们可以将所有变量以标准单位绘制,图形看起来是一样的。这为我们提供了一种比较两个散点图线性程度的方法。

回顾一下,在前面的章节中,我们定义了函数 standard_units,用于将数字数组转换为标准单位。

[In ]:
def standard_units(any_numbers):
    "Convert any array of numbers to standard units."
    return (any_numbers - np.mean(any_numbers))/np.std(any_numbers)  

我们可以使用该函数重新绘制 SUV 的两个散点图,所有变量均以标准单位度量。

[In ]:
Table().with_columns(
    'mpg (standard units)',  standard_units(suv.column('mpg')), 
    'msrp (standard units)', standard_units(suv.column('msrp'))
).scatter(0, 1)
plots.xlim(-3, 3)
plots.ylim(-3, 3);
Scatterplot with 'mpg (standard units)' on the x-axis and 'msrp (standard units)' on the y-axis. There is a clear negative association; as the x value increases, the y value decreases.
[In ]:
Table().with_columns(
    'acceleration (standard units)', standard_units(suv.column('acceleration')), 
    'msrp (standard units)',         standard_units(suv.column('msrp'))
).scatter(0, 1)
plots.xlim(-3, 3)
plots.ylim(-3, 3);
Scatterplot with 'acceleration (standard units)' on the x-axis and 'msrp (standard units)' on the y-axis. There tends to be a positive assocation; as the x value increases so does the y value. There are some notable outliers around x=-1.8 and x=-0.7 which have higher y values than other data points with similar x values.

这些图中看到的关联与之前看到的相同。此外,由于两个散点图现在以完全相同的比例绘制,我们可以看到第二个图中的线性关系比第一个图稍显模糊。

现在我们将定义一个度量,使用标准单位来量化我们所见到的各种关联。

相关系数

“相关系数”度量两个变量之间线性关系的强度。从图形上看,它度量散点图围绕一条直线的聚集程度。

“相关系数”这个术语不太容易说,所以通常简称为“相关性”,用 $r$ 表示。

以下是关于 $r$ 的一些数学事实,我们将通过模拟来观察。

  • 相关系数 $r$ 是介于 $-1$ 和 1 之间的一个数。
  • $r$ 度量散点图围绕一条直线的聚集程度。
  • 如果散点图是一条完美向上倾斜的直线,则 $r = 1$;如果散点图是一条完美向下倾斜的直线,则 $r = -1$。

函数 r_scatter 接受一个 $r$ 值作为参数,并模拟一个相关性非常接近 $r$ 的散点图。由于模拟中的随机性,相关性不会完全等于 $r$。

多次调用 r_scatter,使用不同的 $r$ 值作为参数,观察散点图如何变化。

当 $r=1$ 时,散点图是完美的线性且向上倾斜。当 $r=-1$ 时,散点图是完美的线性且向下倾斜。当 $r=0$ 时,散点图是围绕水平轴的无定形云团,称这两个变量“不相关”。

[In ]:
r_scatter(0.9)
Scatterplot showing a clear positive association. The data points are closely grouped and as the x value increases, so does the y value.
[In ]:
r_scatter(0.25)
Scatterplot with weak positive association. Most data points are in a blob, but you can see around the edges that as the x value increases so does the y value.
[In ]:
r_scatter(0)
Scatterplot showing no association. Unlike the previous graph there is no pattern within the bulk of the data or around the edges.
[In ]:
r_scatter(-0.55)
Scatterplot with negative association; as x values increase the y values tend to decrease. The data points are somewhat blob-like, but have a clear association.

计算 $r$

从我们目前的观察中,$r$ 的公式并不明显。其数学基础超出了本课程的范围。然而,正如你将看到的,计算过程很直接,有助于我们理解 $r$ 的几个性质。

$r$ 的公式

当两个变量均以标准单位度量时,$r$ 是两个变量乘积的平均值。

以下是计算步骤。我们将把这些步骤应用于一个简单的 $x$ 和 $y$ 值表。

[In ]:
x = np.arange(1, 7, 1)
y = make_array(2, 3, 1, 5, 2, 7)
t = Table().with_columns(
        'x', x,
        'y', y
    )
t
x    | y
1    | 2
2    | 3
3    | 1
4    | 5
5    | 2
6    | 7

基于散点图,我们预期 $r$ 为正,但不等于 1。

[In ]:
t.scatter(0, 1, s=30, color='red')
Scatterplot where there is one data point per integer x value. The x-axis is labeled 'x' and y-axis is labeled 'y.' The data points are at (1, 2), (2, 3), (3, 1), (4, 5), (5, 2), and (6, 7).

步骤 1. 将每个变量转换为标准单位。

[In ]:
t_su = t.with_columns(
        'x (standard units)', standard_units(x),
        'y (standard units)', standard_units(y)
    )
t_su
x    | y    | x (standard units) | y (standard units)
1    | 2    | -1.46385           | -0.648886
2    | 3    | -0.87831           | -0.162221
3    | 1    | -0.29277           | -1.13555
4    | 5    | 0.29277            | 0.811107
5    | 2    | 0.87831            | -0.648886
6    | 7    | 1.46385            | 1.78444

步骤 2. 将每一对标准单位相乘。

[In ]:
t_product = t_su.with_column('product of standard units', t_su.column(2) * t_su.column(3))
t_product
x    | y    | x (standard units) | y (standard units) | product of standard units
1    | 2    | -1.46385           | -0.648886          | 0.949871
2    | 3    | -0.87831           | -0.162221          | 0.142481
3    | 1    | -0.29277           | -1.13555           | 0.332455
4    | 5    | 0.29277            | 0.811107           | 0.237468
5    | 2    | 0.87831            | -0.648886          | -0.569923
6    | 7    | 1.46385            | 1.78444            | 2.61215

步骤 3. $r$ 是步骤 2 中计算出的乘积的平均值。

[In ]:
# r is the average of the products of standard units

r = np.mean(t_product.column(4))
r
0.6174163971897709

正如预期,$r$ 为正,但不等于 1。

$r$ 的性质

计算表明:

  • $r$ 是一个纯数字,没有单位。这是因为 $r$ 基于标准单位。
  • 改变任一轴的单位不影响 $r$。这也是因为 $r$ 基于标准单位。
  • 交换坐标轴不影响 $r$。从代数上讲,这是因为标准单位的乘积不依赖于哪个变量被称为 $x$、哪个被称为 $y$。从几何上讲,交换坐标轴使散点图关于直线 $y=x$ 反射,但不会改变聚集程度或关联的符号。
[In ]:
t.scatter('y', 'x', s=30, color='red')
Scatterplot where there is one data point per integer x value, except 4 and 6. This time the x-axis is labeled 'y' and the y-axis is labeled 'x.' Data points are at (1, 3), (2, 5), (3, 2), (5, 4), and (7, 6).

correlation 函数

我们将反复计算相关性,因此定义一个函数来执行上述所有步骤会很有帮助。让我们定义一个函数 correlation,它接受一个表以及表中两列的标签。该函数返回 $r$,即这些列值在标准单位下的乘积的平均值。

[In ]:
def correlation(t, x, y):
    return np.mean(standard_units(t.column(x))*standard_units(t.column(y)))

让我们对 txy 列调用该函数。该函数返回的 $x$ 与 $y$ 之间的相关性与我们直接应用 $r$ 公式得到的结果相同。

[In ]:
correlation(t, 'x', 'y')
0.6174163971897709

正如我们注意到的,变量的指定顺序无关紧要。

[In ]:
correlation(t, 'y', 'x')
0.6174163971897709

对表 suv 的列调用 correlation 可以得到价格与里程之间的相关性以及价格与加速度之间的相关性。

[In ]:
correlation(suv, 'mpg', 'msrp')
-0.6667143635709919
[In ]:
correlation(suv, 'acceleration', 'msrp')
0.48699799279959155

这些值证实了我们之前的观察:

  • 价格与效率之间存在负关联,而价格与加速度之间的关联为正。
  • 价格与加速度之间的线性关系(相关性约 0.5)比价格与里程之间的线性关系(相关性约 -0.67)稍弱。

相关性是一个简单而强大的概念,但有时会被误用。在使用 $r$ 之前,了解相关性度量什么和不度量什么非常重要。

关联不等于因果

相关性仅度量关联。相关并不意味着因果。尽管某学区儿童的体重与数学能力之间的相关性可能是正的,但这并不意味着做数学题会使儿童更重,或者增加体重能提高儿童的数学技能。年龄是一个混杂变量:平均而言,年龄较大的儿童比年龄较小的儿童更重,数学也更好。

相关性度量“线性”关联

相关性只度量一种关联——线性关联。具有强非线性关联的变量可能具有非常低的相关性。以下是一个例子,变量之间存在完美的二次关系 $y = x^2$,但相关性等于 0。

[In ]:
new_x = np.arange(-4, 4.1, 0.5)
nonlinear = Table().with_columns(
        'x', new_x,
        'y', new_x**2
    )
nonlinear.scatter('x', 'y', s=30, color='r')
Scatterplot with the x-axis labeled 'x' and the y-axis labeled 'y.' The data displays a nonlinear U-shaped pattern with the lowest y value at x=0.
[In ]:
correlation(nonlinear, 'x', 'y')
0.0

相关性受异常值影响

异常值可能对相关性产生很大影响。以下是一个例子,原本 $r$ 等于 1 的散点图,仅仅因为添加了一个异常点就变成了 $r$ 等于 0 的图。

[In ]:
line = Table().with_columns(
        'x', make_array(1, 2, 3, 4),
        'y', make_array(1, 2, 3, 4)
    )
line.scatter('x', 'y', s=30, color='r')
Scatterplot with the x-axis labeled 'x' and y-axis labeled 'y.' Data points are at (1, 1), (2, 2), (3, 3), and (4, 4).
[In ]:
correlation(line, 'x', 'y')
1.0
[In ]:
outlier = Table().with_columns(
        'x', make_array(1, 2, 3, 4, 5),
        'y', make_array(1, 2, 3, 4, 0)
    )
outlier.scatter('x', 'y', s=30, color='r')
Scatterplot with the x-axis labeled 'x' and y-axis labeled 'y.' Data points are at (1, 1), (2, 2), (3, 3), (4, 4), and (5, 0).
[In ]:
correlation(outlier, 'x', 'y')
0.0

生态相关性应谨慎解释

基于聚合数据的相关性可能具有误导性。例如,以下是 2014 年 SAT 批判性阅读和数学成绩的数据。50 个州和华盛顿特区各有一个点。Participation Rate 列包含参加考试的高中高年级学生的百分比。接下来的三列显示了该州在考试各部分的平均分,最后一列是考试总分的平均分。

[In ]:
sat2014 = Table.read_table(path_data + 'sat2014.csv').sort('State')
sat2014
State                | Participation Rate | Critical Reading | Math | Writing | Combined
Alabama              | 6.7                | 547              | 538  | 532     | 1617
Alaska               | 54.2               | 507              | 503  | 475     | 1485
Arizona              | 36.4               | 522              | 525  | 500     | 1547
Arkansas             | 4.2                | 573              | 571  | 554     | 1698
California           | 60.3               | 498              | 510  | 496     | 1504
Colorado             | 14.3               | 582              | 586  | 567     | 1735
Connecticut          | 88.4               | 507              | 510  | 508     | 1525
Delaware             | 100                | 456              | 459  | 444     | 1359
District of Columbia | 100                | 440              | 438  | 431     | 1309
Florida              | 72.2               | 491              | 485  | 472     | 1448
... (41 rows omitted)

数学成绩对批判性阅读成绩的散点图非常紧密地聚集在一条直线周围;相关性接近 0.985。

[In ]:
sat2014.scatter('Critical Reading', 'Math')
Scatterplot with 'Critical Reading' on the x-axis and 'Math' on the y-axis. There is a positive correlation; as x values increase, so do the y values. There are no outliers.
[In ]:
correlation(sat2014, 'Critical Reading', 'Math')
0.9847558411067434

这是一个极高的相关性。但需要注意的是,这并不反映“学生”的数学成绩与批判性阅读成绩之间关系的强度。

数据包含各州的平均分。但参加考试的是学生,而不是州。表中的数据是通过将每个州的所有学生合并为一个点(位于该州两个变量的平均值处)而创建的。但该州并非所有学生都处于那个点,因为学生的表现各不相同。如果你为每个学生绘制一个点,而不是为每个州只绘制一个点,那么上图中每个点的周围都会出现一个点云。整体图像将更加模糊。学生的数学成绩与批判性阅读成绩之间的相关性将“低于”基于州平均值计算的值。

基于汇总数据和平均值计算的相关性称为“生态相关性”,并且经常被报告。正如我们刚刚看到的,必须谨慎解释它们。

严肃还是戏谑?

2012 年,备受尊敬的《新英格兰医学杂志》上的一篇论文考察了一组国家中巧克力消费量与诺贝尔奖之间的关系。《科学美国人》严肃地回应了,而其他人则更为轻松。欢迎您自行判断!论文中提供的下图应该会激励您去看一看。

一张风格化的散点图,x 轴为 “Chocolate Consumption kg/yr/capita”,y 轴为 “Nobel Laureates per 10 Million Population”。图上标注了 “r=0.791” 和 “P<0.0001”。我们大致看到正相关;随着 x 值增加,y 值也增加。左下角我们看到中国、日本、葡萄牙、巴西和希腊。美国、法国和芬兰在第三象限(x<7)的簇中具有最大的 x 值。y 值大于 15 的国家是英国、挪威、奥地利、丹麦、瑞典和瑞士。瑞典的 y 值(y~31)远高于其他具有相似 x 值(x~6)的国家。爱尔兰和德国具有高 x 值(分别约为 9 和 11),但与具有相似 x 值的其他国家相比,y 值较低(y~13)。