•概念: 边缘直方图是在使用散点图探索横纵坐标关系的基础上,还使用直方图对横、纵坐标分别进行探索的图像。
•作用: 边缘直方图常用在统计学的探索性分析(EDA)中,以探求数据是否符合统计学的一系列要求,例如线性回归要求残差需满足正态分布等等,在机器学习中,我么也会使用边缘直方图探索数据是否处于偏态,以知道是否需要对数据做归一化或者标准化处理等等!!
•绘制边缘直方图的数据与前几篇博客绘制其它图像的数据是一样的,都是有关于‘车辆相关的信息’的数据
•数据获取参考博客:Python数据可视化之绘制带有最佳拟合线的散点图(图文并茂版!!!),这篇博客详细的介绍了数据的获取来源,对数据的特征值的分析与解读等等
•绘制完成的图像:
•从绘制完成的图像来分析,图像的重难点为:我们应如何在一张画布上绘制两种类型,三个不同的图像呢?
•可以将整个图像看成一个大画布,大画布分成三个小画布,三个小画布来绘制三个图像,这时又有小伙伴会问,三个小画布面积大小不同,应该如何选择呢?
•对于上面的问题来说:我们可以将整个大画布划分成若干个面积相等的正方形,然后按照行、列来选择数量不同但面积大小相同的正方形组成三个画布来绘制图像!!!!
如图所示:
•将图一看成绘制图像的大画布,可将其分成16个大小相等的正方形小画布,然后选择其中的小正方形组合成三个小画布,如下图所示
•上图已经被分成4行、4列的的小正方形,然后使用网格索引的方法来选择小正方形组成三个子图画布!!
•将上述过程描述成Python代码为:
# 创建画布并将画布分割成格子
fig = plt.figure(figsize=(16, 10), dpi=80, facecolor='white')
grid = plt.GridSpec(4, 4, hspace=0.5, wspace=0.2)
# 添加子图
ax_main = fig.add_subplot(grid[:-1, :-1]) # 主图:散点图
ax_right = fig.add_subplot(grid[:-1, -1], xticklabels=[], yticklabels=[]) # 右侧直方图
ax_bottom = fig.add_subplot(grid[-1, :-1], xticklabels=[], yticklabels=[]) # 下侧直方图
•代码解读: fig = plt.figure(figsize=(16, 10), dpi=80, facecolor=‘white’)
创建一个大画布,屏幕分辨率80,背景色为白色
grid = plt.GridSpec(4, 4, hspace=0.5, wspace=0.2)
将上面创建的大画布分成4行、4列的小正方形,格子上下间隔为0.5,左右间隔为0.2
ax_main = fig.add_subplot(grid[:-1, :-1])
创建散点图子图,取第0行取到最后一行前(取左不取右),从第0列取到最后一列前的小正方形组成绘制散点图的画布
ax_right = fig.add_subplot(grid[:-1, -1], xticklabels=[], yticklabels=[])
创建右侧直方图子图,取第0行取到最后一行前,最后一列的小正方形组成绘制右侧直方图的画布,x、y轴标签都为空
ax_bottom = fig.add_subplot(grid[-1, :-1], xticklabels=[], yticklabels=[])
创建下侧直方图子图,取最后一行,从第0列取到最后一列前的小正方形组成绘制下侧直方图的画布,x、y轴标签都为空
•-1 代表最后一行或最后一列,:冒号前后的值都为取左不取右
•上面我们已经将大画布分成了三个小画布来绘制三个不同图像,接下来我们就使用带来实现绘图:
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import pandas as pd
# 获取数据
df = pd.read_csv(r'D:\9\mpg_ggplot2.csv')
# 创建画布并将画布分割成格子
fig = plt.figure(figsize=(16, 10), dpi=80, facecolor='white')
grid = plt.GridSpec(4, 4, hspace=0.5, wspace=0.2)
# 添加子图
ax_main = fig.add_subplot(grid[:-1, :-1])
ax_right = fig.add_subplot(grid[:-1, -1], xticklabels=[], yticklabels=[])
ax_bottom = fig.add_subplot(grid[-1, :-1], xticklabels=[], yticklabels=[])
# 在中心绘制气泡图
ax_main.scatter('displ', 'hwy'
, s=df.cty * 4 # 点的大小
, data=df #数据集
, c=df.manufacturer.astype('category').cat.codes # 颜色列表
, cmap='tab10' # 调色板
, edgecolors='gray' # 边缘颜色
, linewidth=.5 # 线宽
, alpha=.9) # 透明度
# 绘制底部直方图
ax_bottom.hist(df.displ, 40, histtype='stepfilled', orientation='vertical', color='deeppink')
ax_bottom.invert_yaxis() # 让y轴反向
# 绘制右边直方图
ax_right.hist(df.hwy, 40, histtype='stepfilled', orientation='horizontal', color='deeppink')
# 装饰图像
plt.rcParams['font.sans-serif'] = ['Simhei']
ax_main.set(title='边缘直方图 \n 发动机排量 vs 公路里程/加仑'
, xlabel='发动机排量(L)'
, ylabel='公路里程/加仑')
ax_main.title.set_fontsize = (20)
for item in ([ax_main.xaxis.label, ax_main.yaxis.label] + ax_main.get_xticklabels() + ax_main.get_yticklabels()):
item.set_fontsize(14)
for item in [ax_bottom, ax_right]:
item.set_xticks([]) # 去掉直方图的标尺
item.set_yticks([])
label_format = '{:,.1f}' # 创建浮点数格式 .1f一位小数
xlabels = ax_main.get_xticks().tolist()
ax_main.xaxis.set_major_locator(mticker.FixedLocator(xlabels)) # 定位到散点图的x轴
ax_main.set_xticklabels([label_format.format(x) for x in xlabels]) # 使用列表推导式循环将刻度转换成浮点数
plt.show()
•在将x轴刻度转换成浮点数时,我们可能会使用下述代码:
xlabels = ax_main.get_xticks().tolist() # 将刻度值转换成浮点数
ax_main.set_xticklabels(xlabels) # 设置刻度值为浮点数
plt.show()
•但是,使用上述代码会出现上图警告,但图像是绘制正确的!!
•解决此警告参考博客,博客中详细解释了出现警告的原因及解决方法:解决警告:UserWarning: FixedFormatter should only be used together with FixedLocator(图文并茂版!!!)
•最后根据分析图像,我们就成功的绘制出散点图(实为气泡图)的边缘直方图!!!