节选自《Python预测之美:数据分析与算法实战》。


相关关系是一种非确定的关系,就好像身高与体重的关系一样,它们之间不能用一个固定的函数关系来表示。而相关分析就是研究这种随机变量间相关关系的统计方法。此处,主要探讨不同特征对研究对象的相关性影响。常见进行相关分析的方法,主要有散点图和相关图。

1.散点图

散点图就是数据点在直角坐标系上的分布图,通常分为散点图矩阵和三维散点图。其中散点矩阵是由变量两两组合由数据点分布图构成的矩阵,而三维散点图就是从所有变量中选择三个变量进行绘制,进一步在三维空间里观察数据的形态。

(1)散点图矩阵

Pandas是Python数据分析非常重要的一个库,它自带了很多统计分析及绘图的功能,这其中就包含散点图矩阵的绘制方法,即在Pandas.plotting模块下的scatter_matrix函数。使用该函数可快速绘制散点图矩阵。这里,我们以iris数据集为例,分析鸢尾花的Sepal.Length、Sepal.Width、Petal.Length、Petal.Width这四个指标的相关关系。并用scatter_matrix绘制散点图矩阵,代码如下

import pandas as pd
import matplotlib.pyplot as plt
iris = pd.read_csv('iris.csv')
# 参数说明
# figsize=(10,10) 设置画布大小为10x10
# alpha=1,设置透明度,此处设置为不透明
# hist_kwds={"bins":20} 设置对角线上直方图参数
# 可通过设置diagonal参数为kde将对角图像设置为密度图
pd.plotting.scatter_matrix(iris,figsize=(10,10),alpha=1,hist_kwds={"bins":20})
plt.show()


图3-1-3-1 使用pandas绘制散点图矩阵

如图,为所有变量的两两组合的散点图矩阵,每个散点图中呈现的是任意两变量的数据点,可通过数据点的分布,了解变量之间的相关性,对角线上为单变量的直方分布图。此图中Petal.Length与Petal.Width对应的散点图比较接近线性,说明这两个变量间的相关性较强。

此外,我们还可以使用seaborn库下面的pairplot函数来绘制散点图矩阵。针对鸢尾花的Sepal.Length、Sepal.Width、Petal.Length、Petal.Width这四个指标,使用pairplot函数绘制散点图,代码如下

import seaborn as sns
sns.pairplot(iris,hue="Species")
plt.show()


图3-1-3-2 使用seaborn库绘制散点图矩阵

如代码所示,通过hue参数指定了分组的变量,这里使用鸢尾花的种类进行分组。如图3-1-3-2,对角线上的图形表示各个变量在不同鸢尾花类型下的分布情况;其他图形分别用不同颜色为数据点着色。根据该图可以更进一步地知道不同类型鸢尾花各变量的相关关系,以及线性及非线性变化规律。

然而,使用seaborn库来绘制散点图矩阵有个问题,就是不能同时用颜色和形状来表示分类。有数据分析中,我们经常会有这样的需求,即用颜色来表示真实的类别,用形状来表示预测的类别,那么通过一个图就可以直观地看到预测建模的效果。既然seaborn不能直接支持,那该如何实现呢?我们可以基于matplotlib库自己实现,自定义函数pair_plot,代码如下

def pair_plot(df,plot_vars,colors,target_types,markers,color_col,marker_col,fig_size=(15,15)):
# 设置画布大小
plt.figure(figsize=fig_size)
plot_len = len(plot_vars)
index = 0
for p_col in range(plot_len):
col_index = 1
for p_row in range(plot_len):
index = index + 1
plt.subplot(plot_len, plot_len, index)
if p_row != p_col:
# 非对角位置,绘制散点图
df.apply(lambda row:plt.plot(row[plot_vars[p_row]],row[plot_vars[p_col]],
color=colors[int(row[color_col])],
marker=markers[int(row[marker_col])],linestyle=''),axis=1)
else:
# 对角位置,绘制密度图
for ci in range(len(colors)):
sns.kdeplot(df.iloc[np.where(df[color_col]==ci)[0],p_row],
shade=True, color=colors[ci],label=target_types[ci])
# 添加横纵坐标轴标签
if col_index == 1:
plt.ylabel(plot_vars[p_col])
col_index = col_index + 1
if p_col == plot_len - 1:
plt.xlabel(plot_vars[p_row])
plt.show()

如代码所示,该函数主要使用subplot机制来绘制子图,通过

(n为变量个数)个子图的布局来实现散点图矩阵。进一步,我们使用iris数据集,基于pair_plot函数来绘制散点图矩阵,代码如下

# 重置变量名称
features = ['sepal_length','sepal_width','petal_length','petal_width']
iris_df=iris.drop(columns='Species')
iris_df.columns = features
# 此处,我们建立两个新变量,都存储花色分类值,其中type对应真实类别,cluster对应预测类别
iris_df['type'] = iris.Species
iris_df['cluster'] = iris.Species
# 将cluster变量转化为整数编码
iris_df.cluster = iris_df.cluster.astype('category')
iris_df.cluster = iris_df.cluster.cat.codes
# 将type变量转化为整数编码
iris_df.type = iris_df.type.astype('category')
iris_df.type = iris_df.type.cat.codes
# 获得花色类别列表
types = iris.Species.value_counts().index.tolist()
pair_plot(df=iris_df,
plot_vars=features,
colors=['#50B131','#F77189','#3BA3EC'], # 指定描述三种花对应的颜色
target_types = types,
markers= ['*','o','^'], # 指定预测类别cluster对应的形状
color_col='type', # 对应真实类别变量
marker_col='cluster') # 对应预测类别变量


图3-1-3-3 修正的散点图矩阵

如图3-1-3-3所示,散点图中使用到了颜色和形状来区别不同的样本,在真实的应用场景中,可以将颜色和形状对应不同的类别,比如真实分类与预测分类,然后巧妙地使用散点图矩阵,直观地分析预测效果。

(2)三维散点图

常用于绘制三维散点图的方法是使用mpl_toolkits库,该库下的mplot3d模块可以帮助我们绘制三维图形。主要使用到的是Axes3D类。这里,仍然使用iris数据集,通过使用Axes3D类对应实例中的函数绘制鸢尾花的Sepal.Length、Petal.Length、Petal.Width这三个指标在三维空间的散点图,代码如下:import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
dims = {'x':'Sepal.Length','y':'Petal.Length','z':'Petal.Width'}
types = iris.Species.value_counts().index.tolist()
# 绘制散点图
fig = plt.figure()
ax = Axes3D(fig)
for iris_type in types:
tmp_data = iris[iris.Species==iris_type]
x,y,z = tmp_data[dims['x']], tmp_data[dims['x']], tmp_data[dims['z']]
ax.scatter(x, y, z, label=iris_type)
# 绘制图例
ax.legend(loc='upper left')
# 添加坐标轴(顺序是Z, Y, X)
ax.set_zlabel(dims['z'])
ax.set_ylabel(dims['y'])
ax.set_xlabel(dims['x'])
plt.show()

图3-1-3-4 三维散点图
如图3-1-3-4,该函数为三维空间中的点拟合了线性平面,通过切换坐标轴可以更直观地观察数据的分布规律。

2.相关图
所谓相关图是基于变量间的相关关系大小,通过可视化方式反应不同变量组合间相关关系的差异的图形。可以把相关图分为相关矩阵图、相关层次图。
(1)相关矩阵图
Python中绘制相关矩阵图,可使用seaborn库的heatmap方法,但笔者觉得不太美观,于是想自己实现一个。在绘制相关矩阵图时,需要数据中两两变量相关系数矩阵的数据,该数据中可以看到对应不同变量间的相关系数大小。在Python中,可以使用pandas.corr函数来实现。这里,我们以iris数据集为例,说明获取相关系数矩阵的用法,代码如下:df=iris.drop(columns='Species')
corr = df.corr()
corr
Sepal.Length
Sepal.Width
Petal.Length
Petal.WidthSepal.Length
1.000000
-0.117570
0.871754
0.817941
Sepal.Width
-0.117570
1.000000
-0.428440
-0.366126
Petal.Length
0.871754
-0.428440
1.000000
0.962865
Petal.Width
0.817941
-0.366126
0.962865
1.000000

如上表所示,对角线上的值都为1,表示变量与自己的相关系数为1。相关系数介于-1到1之间,绝对值越大,相关性越强,大于0时表示正相关,小于0时表示负相关,为0时,表示没有相关性。进一步,编写自定义函数corrplot来实现相关矩阵图的绘制功能,代码如下

def corrplot(corr,cmap,s):
#使用x,y,z来存储变量对应矩阵中的位置信息,以及相关系数
x,y,z = [],[],[]
N = corr.shape[0]
for row in range(N):
for column in range(N):
x.append(row)
y.append(N - 1 - column)
z.append(round(corr.iloc[row,column],2))
# 使用scatter函数绘制圆圈矩阵
sc = plt.scatter(x, y, c=z, vmin=-1, vmax=1, s=s*np.abs(z), cmap=plt.cm.get_cmap(cmap))
# 添加颜色板
plt.colorbar(sc)
# 设置横纵坐标轴的区间范围
plt.xlim((-0.5,N-0.5))
plt.ylim((-0.5,N-0.5))
# 设置横纵坐标轴值标签
plt.xticks(range(N),corr.columns,rotation=90)
plt.yticks(range(N)[::-1],corr.columns)
# 去掉默认网格
plt.grid(False)
# 使用顶部的轴做为横轴
ax = plt.gca()
ax.xaxis.set_ticks_position('top')
# 重新绘制网格线
internal_space = [0.5 + k for k in range(4)]
[plt.plot([m,m],[-0.5,N-0.5],c='lightgray') for m in internal_space]
[plt.plot([-0.5,N-0.5],[m,m],c='lightgray') for m in internal_space]
# 显示图形
plt.show()

代码中,我们主要使用了plt.scatter函数来绘制圆圈,圆圈的大小表示相关性程度,圆圈的颜色表示相关性大小(有方向),通过横纵向等间距摆放这些圆圈的方式来展示相关矩阵图。然后,我们基于已经得到corr数据,绘制相关矩阵图,代码如下

corrplot(corr,cmap="Spectral",s=2000)


图3-1-3-5 相关矩阵图

如图,左侧是由圆圈组成的相关矩阵,右侧是颜色板,可以直接地看到,Petal.Length与Petal.Width具有较强的正相关性,而Sepal.Length与Sepal.Width的相关性则较弱。

(2)相关层次图

相关层次图,是通过计算变量间的距离来判断各变量是否属于同一类的方法,体现的是变量之间的相关性。此处,通过将相关系数转化为距离度量,进行系统聚类,旨在分析各变量的相关关系及组合影响情况。通常有如下四种方法将相关系数转化为相异性度量:

, r为相关系数;②

;③

;④

。现选用第四种相异性度量,使用mtcars数据集,进行系统聚类,代码如下

import pandas as pd
import numpy as np
mtcars = pd.read_csv("mtcars.csv")
mtcars.drop(columns="_",inplace=True)
# 计算第四种相异性度量
d=np.sqrt(1-mtcars.corr()*mtcars.corr())
from scipy.spatial.distance import pdist,squareform
from scipy.cluster.hierarchy import linkage
from scipy.cluster.hierarchy import dendrogram
row_clusters = linkage(pdist(d,metric='euclidean'),method='ward')row_dendr = dendrogram(row_clusters,labels = d.index)
plt.tight_layout()
plt.ylabel('Euclidean distance')plt.plot([0,2000],[1.5,1.5],c='gray',linestyle='--')
plt.show()


图3-1-3-6  相关层次图

如图3-1-3-6可知,变量drat、am、gear相关性较强,cyl、disp、mpg、wt相关性较强,并且hp、vs、qsec、carb具有较强的相关性。

参加送书活动