可视化之美_布局

人工智能技术栈 / 2024-01-21 / 原文

目录
  • 一、图形对象
    • 1.1 大小尺寸
    • 1.2 分辨率
    • 1.3 边距
  • 二、使用subplot
      • (2)函数返回值
      • (3)示例
    • 2.2 基于seaborn库的箱线图绘制
    • 附录
    • 本文相关待扩展阅读

📑 用到的Python函数:

  • matplotlib.grid.GridSpec():创建和配置复杂的子图网格布局,以便在一个图形窗口中放置多个子图
  • matplotlib.gridspec.subplotSpec:用于定义和控制子图在网格布局中的位置和大小
  • matplotlib.pyplot.contour():绘制等高线图
  • matplotlib.pyplot.contourf():绘制填充等高线图
  • matplotlib.pyplot.figure():创建一个心的图形窗口或图表对象,以便在其上进行绘图操作
  • matplotlib.pyplot.rcParams:获取或设置全局绘图参数的默认值,如图形尺寸、字体大小、线条样式等
  • matplotlib.pyplot.scatter():绘制散点图
  • matplotlib.pyplot.subplot():用于在当前图形窗口中创建一个子图,并定位该子图在整个图形窗口中的位置
  • matplotlib.pyplot.subplots():一次性创建一个包含多个子图的图形窗口,并返回一个包含子图对象的元组
  • numpy.linspace():在指定的间隔内,返回固定步长的数据
  • numpy.meshgrid():产生网格化数据
  • numpy.random.multivariate_normal():用于生成多元正态分布的随机样本
  • numpy.vstack():返回竖直堆叠后的数组
  • scipy.stats.gaussian_kde():高斯核密度估计
  • statsmodels.api.nonparametric.KDEUnivariate():构造一元KDE

一、图形对象

1.1 大小尺寸

matplotlib中默认图形尺寸为:宽6.4英尺,高4.8英尺(1英尺约为2.54厘米),即默认图片尺寸为宽约16厘米,高约12厘米。可使用figure函数,并指定figsize参数来设置图像的宽度和高度,figsize参数接受一个元组(宽度,高度),单位为英尺。

1.2 分辨率

默认图片以一个dpidots per inch,每英尺点数)为100的分辨率显示。比如将分辨率设置为300的代码如下所示:

import maptplotlib.pyplot as plt

plt.rcParams['figure.dpi'] = 300

如果想保存图像到文件,可使用savefig函数,并通过设置dpi参数来指定分辨率。例如,保存图像为300dpi的高质量PNG文件,可使用如下指令来实现:

import maptplotlib.pyplot as plt

plt.savefig('plot_name.png', dpi=300)

对于Seaborn,可通过如下指令来修改图像的分辨率:

import seaborn as sns

sns.set(rc={"figure.dpi":300, "savefig.dpi":300})

1.3 边距

一张图片的边距(margin)即为其上线左右的留白。在matplotlib默认情况下,图像的边距为:

figure.subplot.left: 0.125
figure.subplot.right: 0.9
figure.subplot.top: 0.88
figure.subplot.bottom: 0.11

如图 1所示,这些参数的值为0~1之间的浮点数,相当于图像的宽度或高度的百分比。

默认情况下,在宽度方向上,left = 0.125表示左边距相对于图像宽度的12.5%right = 0.9表示右边距相对于图像宽度的90%

高度方向来看,top = 0.88表示图像顶边位于图像高度的88%。而bottom = 0.1表示底边距相对于图像高度的10%

注意:(0, 0)表示图形左下角,(1, 1)表示图形右上角。

图1 图片宽度、高度百分比

二、使用subplot

(1)标准正态分布核密度函数、箱线图以及小提琴图的绘制

对于正态分布数据,下面定义一个函数用于绘制如下内容:

  • 带有内核密度曲线的正态分布直方图;
  • 箱线图;
  • 小提琴图
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import rcParams

#! 解决不显示的问题:中文设置为宋体格式
plt.rcParams['font.family'] = ["Times New Roman", 'SimSun']

rcParams['xtick.direction'] = 'in'
rcParams['ytick.direction'] = 'in'

# 绘制正态分布核密度函数、箱线图以及小提琴图的函数
def plot_comparison(x, title):
    fig, ax = plt.subplots(3, 1, figsize=(7, 5), sharex=True)

    sns.distplot(x, ax=ax[0])
    ax[0].set_title("Histogram + KDE", fontsize=12)
    ax[0].tick_params(axis="both", labelsize=11)
    # ax[0].yaxis.grid(True, zorder=-1)

    sns.boxplot(x, ax=ax[1])
    ax[1].set_title("Boxplot", fontsize=12)
    ax[1].set_ylabel("label", fontsize=12)
    # ax[1].xaxis.grid(True)

    sns.violinplot(x, ax=ax[2])
    ax[2].set_title("Violin plot", fontsize=12)
    ax[2].set_ylabel("label", fontsize=12)
    ax[2].tick_params(axis="both", labelsize=11)
    # ax[2].xaxis.grid(True)

    fig.suptitle(title, fontsize=14)
    plt.show()

# 函数的调用与图片绘制
N = 10 ** 4
sample_gaussian = np.random.normal(size=N)
plot_comparison(sample_gaussian, '标准正态分布')

由上图可以看出,小提琴图的核密度图与添加在直方图上的核密度图是一样的。小提琴图中较宽的部分代表观测值取值的概率较高,较窄的部分则对应于较低的概率。然而这在箱线图中是无法直观表示的,因此小提琴图比箱形图包含更多的数据分布信息。

注意💥:对于细节属性参数需要输入字典格式的数据,其设置方法可参考📖 python-matplotlib | 箱线图及解读 - 知乎

(2)函数返回值

vilinplot()函数的返回值为包含小提琴图相应组件的字典,每个字典元素以列表形式表示:

  • bodies:每个小提琴填分布充面积的PolyCollection实例对象;
  • cmeans:每个小提琴分布的均值的LineCollection实例对象;
  • cmins:小提琴分布下边界的LineCollection实例对象;
  • cmaxes:小提琴分布上边界的LineCollection实例对象;
  • cbars:小提琴分布的分为数线条的LineColletion实例对象;
  • cmedians:每个小提琴分布的中位数的LineCollection实例对象。
  • cquantiles:每个小提琴分位数的LineCollection实例对象。

注意💥:如果不启用小提琴图的相应元素,相应键值则返回空列表。

(3)示例

更为详细的内容可参考matplotlib官方手册📚:matplotlib.pyplot.violinplot — Matplotlib 3.7.2 documentation。这里选取matplotlib官网上一个具有代表性的小提琴图示例作为演示对象(参考🎨:Violin plot customization — Matplotlib 3.7.2 documentation)。在官网示例的基础上,本文添加了相关参数的使用方法并对代码进行注释,代码如下所示:


代码执行结果如下图所示

后续替换中文为宋体的图片

2.2 基于seaborn库的箱线图绘制

Seaborn是基于matplotlib的python数据可视化库。它提供了高层级的接口用于画出统计图。它与pandas库数据接口非常相近,可以直接使用pandas的数据结构。相比较于matplotlib的箱线图绘制,searborn绘制的更加美观。seaborn中绘制箱线图的函数为boxplot(),其函数原型如下所示:

seaborn.boxplot(data=None, *, x=None, y=None, hue=None, hue_order=None, orient=None, color=None, palette=None, saturation=0.75, width=0.8, dodge=True, fliersize=5, linewidth=None, whis=1.5, ax=None, **kwargs)

注意💥:
(1)虽然seaborn的boxplot()能以arraylist以及DataFrame。但是其更适合于对DataFrame格式的数据进行箱线图绘制。因此,在绘制箱线图之前,建议将数据转换为DataFrame格式。本文的介绍以DataFrame格式的数据为例
(2)由于seaborn是基于matplotlib的,因此我们可以直接调用matplotlib.boxplot的参数对箱线图进行设置。

防采坑💣:在使用df = sns.load_dataset("titanic")导入seaborn自带的数据时,由于网络原因会出现加载不了的问题。对此,可参考博文📖 解决seaborn数据无法导入的问题_无法解析导入 seaborn_ryo007gnnu的博客-CSDN博客进行排雷。

附录

博文鉴赏:

  • 📖 概率分布的python实现 - camash - 博客园
  • 📖 如何通俗的理解小提琴图 - 知乎
  • 📖 matplotlib.axes.Axes.violinplot — Matplotlib 3.7.2 documentation
  • 📖
  • 📖

本文相关待扩展阅读