当前位置: 移动技术网 > IT编程>脚本编程>Python > 基于Python实现相关分析案例

基于Python实现相关分析案例

2020年07月11日  | 移动技术网IT编程  | 我要评论

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

image.png

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

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,该函数为三维空间中的点拟合了线性平面,通过切换坐标轴可以更直观地观察数据的分布规律。

image.png

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.Width
Sepal.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具有较强的相关性。

参加送书活动

image.png

活动截止日期2020-07-13,微信扫码,关注 数海星辰 公众号,回复“0709”,即可参加送书活动。

image.png

数海星辰,作者官方公众号

本文地址:https://blog.csdn.net/u013524655/article/details/107238798

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网