在众多的可视化图形中,有一类图形专门用于探究两个或三个变量之间的关系。例如,散点图用于发现两个数值变量之间的关系,气泡图可以展现三个数值变量之间的关系,热力图则体现了两个离散变量之间的组合关系。下面首先了解一下最常用的散点图是如何绘制的。
1 散点图
如果需要研究两个数值型变量之间是否存在某种关系,例如正向的线性关系,或者是趋势性的非线性关系,那么散点图将是最佳的选择。
seaborn模块绘制散点图 为了使读者清楚地掌握lmplot函数的使用方法,有必要介绍一下该函数的语法和参数含义:
lmplot(x, y, data, hue=None, col=None, row=None, palette=None, col_wrap=None,
size=5, aspect=1, markers='o', sharex=True, sharey=True, hue_order=None,
col_order=None, row_order=None, legend=True, legend_out=True, scatter=True,
fit_reg=True, ci=95, n_boot=1000, order=1, logistic=False, lowess=False,
robust=False, logx=False, x_partial=None, y_partial=None, truncate=False,
x_jitter=None, y_jitter=None, scatter_kws=None, line_kws=None)
- x,y:指定x轴和y轴的数据。
- data:指定绘图的数据集。
- hue:指定分组变量。
- col,row:用于绘制分面图形,指定分面图形的列向与行向变量。
- palette:为hue参数指定的分组变量设置颜色。
- col_wrap:设置分面图形中每行子图的数量。
- size:用于设置每个分面图形的高度。
- aspect:用于设置每个分面图形的宽度,宽度等于size*aspect。
- markers:设置点的形状,用于区分hue参数指定的变量水平值。
- sharex,sharey:bool类型参数,设置绘制分面图形时是否共享x轴和y轴,默认为True。
- hue_order,col_order,row_order:为hue参数、col参数和row参数指定的分组变量设值水平值顺序。
- legend:bool类型参数,是否显示图例,默认为True。
- legend_out:bool类型参数,是否将图例放置在图框外,默认为True。
- scatter:bool类型参数,是否绘制散点图,默认为True。
- fit_reg:bool类型参数,是否拟合线性回归,默认为True。
- ci:绘制拟合线的置信区间,默认为95%的置信区间。
- n_boot:为了估计置信区间,指定自助重抽样的次数,默认为1000次。
- order:指定多项式回归,默认指数为1。
- logistic:bool类型参数,是否拟合逻棒回归,默认为False。
- logx:bool类型参数,是否对x轴做对数变换,默认为False。
- x_partial,y_partial:为x轴数据和y轴数据指定控制变量,即排除x_partial和y_partial变量的影响下绘制散点图。
- truncate:bool类型参数,是否根据实际数据的范围对拟合线做截断操作,默认为False。
- x_jitter,y_jitter:为x轴变量或y轴变量添加随机噪声,当x轴数据与y轴数据比较密集时,可以使用这两个参数。
- scatter_kws:设置点的其他属性,如点的填充色、边框色、大小等。 line_kws:设置拟合线的其他属性,如线的形状、颜色、粗细等。
该函数的参数虽然比较多,但是大多数情况下读者只需使用几个重要的参数,如x、y、hue、data等。接下来以iris数据集为例(数据集可自行百度获取),绘制分组散点图,绘图代码如下:
zhfont = mpl.font_manager.FontProperties(fname='/usr/share/fonts/truetype/liberation/simhei.ttf')
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 导入第三方模块
from matplotlib.font_manager import FontProperties
# 设置字体属性
font_path = '/usr/share/fonts/truetype/liberation/simhei.ttf' # 替换为实际的字体文件路径
font_properties = FontProperties(fname=font_path)
# 导入第三方模块
import pandas as pd
# 读入数据
iris=pd.read_csv(r'/content/drive/MyDrive/Colab_Notebooks/DraftTableFiles/iris.csv')
# seaborn模块绘制分组散点图
sns.lmplot(x='Petal.Length', # 指定x轴变量
y='Petal.Width', # 指定y轴变量
hue='Species', # 指定分组变量
data=iris, # 指定绘图数据集
legend_out=False, # 将图例呈现在图框内
truncate=True # 根据实际的数据范围,对拟合线做截断操作
)
# 修改x轴和y轴标签
plt.xlabel('花瓣宽度',fontproperties=font_properties)
plt.ylabel('花瓣长度',fontproperties=font_properties)
# 添加标题
plt.title('鸢尾花的花瓣宽度与长度关系',fontproperties=font_properties)
# 显示图形
plt.show()

图1
如图1所示,lmplot函数不仅可以绘制分组散点图,还可以对每个组内的散点添加回归线(图1默认拟合线性回归线)。分组效果的体现是通过hue参数设置的,如果需要拟合其他回归线,可以指定lowess参数(局部多项式回归)、logistic参数(逻辑回归)、order参数(多项式回归)和robust参数(鲁棒回归)。
2 气泡图
散点图反映两个数值型变量的关系,如果还想通过散点图添加第三个数值型变量的信息,一般可以使用气泡图。气泡图的实质就是通过第三个数值型变量控制每个散点的大小,点越大,代表的第三维数值越高,反之亦然。接下来将会介绍如何通过Python绘制气泡图。
应用matplotlib模块中的scatter函数可绘制散点图,本节将使用该函数绘制气泡图。要实现气泡图的绘制,关键的参数是s,即散点图中点的大小,如果将数值型变量传递给该参数,就可以轻松绘制气泡图了。如下是一个代码示例:
zhfont = mpl.font_manager.FontProperties(fname='/usr/share/fonts/truetype/liberation/simhei.ttf')
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 导入第三方模块
from matplotlib.font_manager import FontProperties
# 设置字体属性
font_path = '/usr/share/fonts/truetype/liberation/simhei.ttf' # 替换为实际的字体文件路径
font_properties = FontProperties(fname=font_path)
# 读取数据
Prod_Category=pd.read_excel(r'/content/drive/MyDrive/Colab_Notebooks/DraftTableFiles/SuperMarket.xlsx')
# 将利润率标准化到[0,1]之间(因为利润率中有负数),然后加上微小的数值0.001
range_diff=Prod_Category.Profit_Ratio.max()-Prod_Category. Profit_Ratio.min()
Prod_Category['std_ratio']=(Prod_Category.Profit_Ratio-Prod_Category. Profit_Ratio.min())/range_diff + 0.001
# 绘制办公用品的气泡图
plt.scatter(x=Prod_Category.Sales[Prod_Category.Category == '办公用品'],
y=Prod_Category.Profit[Prod_Category.Category == '办公用品'],
s=Prod_Category.std_ratio[Prod_Category.Category == '办公用品'] *500,color='steelblue', label='办公用品', alpha=0.6
)
# 绘制技术产品的气泡图
plt.scatter(x=Prod_Category.Sales[Prod_Category.Category == '技术产品'],
y=Prod_Category.Profit[Prod_Category.Category == '技术产品'],
s=Prod_Category.std_ratio[Prod_Category.Category == '技术产品'] *500,
color='indianred' , label='技术产品',alpha=0.6
)
# 绘制家具产品的气泡图
plt.scatter(x=Prod_Category.Sales[Prod_Category.Category == '家具产品'],
y=Prod_Category.Profit[Prod_Category.Category == '家具产品'],
s=Prod_Category.std_ratio[Prod_Category.Category == '家具产品'] *500,
color='black' , label='家具产品', alpha=0.6
)
# 添加x轴和y轴标签
plt.xlabel('销售额',fontproperties=font_properties)
plt.ylabel('利润',fontproperties=font_properties)
# 添加标题
plt.title('销售额、利润及利润率的气泡图',fontproperties=font_properties)
# 显示图例
legend = plt.legend(prop=zhfont)
# 显示图形
plt.show()

图2
如图2所示,应用scatter函数绘制了分组气泡图,从图中可知,办公用品和家具产品的利润率波动比较大(因为这两类圆点大小不均)。从代码角度来看,绘图的核心部分是使用三次scatter函数,而且代码结构完全一样,如果读者对for循环掌握得比较好,完全可以使用循环的方式替换三次scatter函数的重复应用。
需要说明的是,如果s参数对应的变量值小于等于0,则对应的气泡点是无法绘制出来的。这里提供一个解决思路,就是先将该变量标准化为[0,1],再加上一个非常小的值,如0.001。如上代码所示,最后对s参数扩大500倍的目的就是凸显气泡的大小。
遗憾的是,pandas模块和seaborn模块中没有绘制气泡图的方法或函数,故这里就不再衍生了。如果读者确实需要绘制气泡图,又觉得matplotlib模块中的scatter函数用起来比较烦琐,可以使用Python的bokeh模块,有关该模块的详细内容,可以查看官方文档。
3 热力图
热力图,有时也称之为交叉填充表。该图形最典型的用法就是实现列联表的可视化,即通过图形的方式展现两个离散变量之间的组合关系。读者可以借助于seaborn模块中的heatmap函数,完成热力图的绘制。首先对该函数的用法及参数含义做如下解释:
heatmap(data, vmin=None, vmax=None, cmap=None, center=None, annot=None,
fmt='.2g',annot_kws=None, linewidths=0, linecolor='white',
cbar=True, cbar_kws=None, square=False, xticklabels='auto',
yticklabels='auto', mask=None, ax=None)
- data:指定绘制热力图的数据集。
- vmin,vmax:用于指定图例中最小值与最大值的显示值。
- cmap:指定一个colormap对象,用于热力图的填充色。
- center:指定颜色中心值,通过该参数可以调整热力图的颜色深浅。
- annot:指定一个bool类型的值或与data参数形状一样的数组,如果为True,就在热力图的每个单元上显示数值。
- fmt:指定单元格中数据的显示格式。
- annot_kws:有关单元格中数值标签的其他属性描述,如颜色、大小等。
- linewidths :指定每个单元格的边框宽度。
- linecolor:指定每个单元格的边框颜色。
- cbar:bool类型参数,是否用颜色条作为图例,默认为True。
- cbar_kws:有关颜色条的其他属性描述。
- square:bool类型参数,是否使热力图的每个单元格为正方形,默认为False。
- xticklabels,yticklabels:指定热力图x轴和y轴的刻度标签,如果为True,则分别以数据框的变量名和行名称作为刻度标签。
- mask:用于突出显示某些数据。
- ax:用于指定子图的位置。
下面是一个代码示例:
import numpy as np
# 读取数据
Sales=pd.read_excel(r'/content/drive/MyDrive/Colab_Notebooks/DraftTableFiles/Sales.xlsx')
# 根据交易日期,衍生出年份和月份字段
Sales['year']=Sales.Date.dt.year
Sales['month']=Sales.Date.dt.month
# 统计每年各月份的销售总额
Summary=Sales.pivot_table(index='month', columns='year', values='Sales', aggfunc=np.sum)
# 绘制热力图
sns.heatmap(data=Summary, # 指定绘图数据
cmap='PuBuGn', # 指定填充色
linewidths=.1, # 设置每个单元格边框的宽度
annot=True, # 显示数值
fmt='.1e' # 以科学计算法显示数据
)
#添加标题
plt.title('每年各月份销售总额热力图',fontproperties=font_properties)
# 显示图形
plt.show()

图3
如图3所示就是将表格进行可视化的结果,每个单元格颜色的深浅代表数值的高低,通过颜色就能迅速发现每年各月份销售情况的好坏。