Matplotlib(五)- 绘制子图

文章目录

  • 一、子图概述
    • 1. 子图介绍
    • 2. 子图布局
      • 2.1 网格布局
      • 2.2 自由布局
  • 二、绘制等分区域子图
    • 1. 使用 plt.subplot() 绘制子图
      • 示例:绘制多个子图
      • 示例:工业月度同比情况
    • 2. 使用 plt.subplots() 绘制子图
      • 示例:绘制多个子图
      • 示例:部分国家养猫与养狗人群比例
  • 三、绘制跨越区域子图
    • 1. 使用 plt.subplot2grid() 绘制子图
    • 2. 示例:抖音和快手用户画像对比
  • 四、绘制自定义区域子图
    • 1. 通过 GridSpec 类绘制
      • 示例:使用 GridSpec 创建布局
    • 2. 通过 add_gridspec() 方法绘制
      • 示例:使用 add_gridspec() 创建布局
  • 五、子图坐标轴共享
    • 1. 共享相邻子图的坐标轴
      • 1.1 共享相邻子图的坐标轴介绍
      • 1.2 `plt.subplot()` 和 `plt.subplots()` 方法中的参数 `sharex` 或 `sharey` 的取值
      • 1.3 示例:部分国家养猫与养狗人群比例
    • 2. 共享非相邻子图的坐标轴
      • 2.1 共享非相邻子图的坐标轴介绍
      • 2.2 示例:非相邻子图坐标轴共享
    • 3. 同一子图共享坐标轴(双 Y 轴)
      • 3.1 同一子图共享 x 坐标轴介绍
      • 3.2 示例:某地区全年气温与降水量、蒸发量的关系
  • 六、子图布局
    • 1. 约束布局
      • 1.1 约束布局介绍
      • 1.2 启用约束布局
        • 1.2.1 全局启用
        • 1.2.2 局部启用
        • 1.2.3 自定义约束布局参数
        • 1.2.4 示例:绘制多个子图(约束布局)
    • 2. 紧密布局
      • 2.1 紧密布局介绍
      • 2.2 启用紧密布局
        • 2.2.1 通过 tight_layout() 启用
        • 2.2.2 使用 subplots() 或 figure() 方法中的 layout 参数
        • 2.2.3 通过 figure.autolayout 配置项启用
        • 2.2.4 示例:绘制多个子图(紧密布局)


一、子图概述

在数据可视化中,当需要同时展示多组数据或从不同维度呈现同一数据时,子图(Subplot)是一种高效的解决方案。通过将多个图表合理排布在同一画布上,既能保证数据间的关联性,又能实现对比分析,提升信息传递的效率。

1. 子图介绍

子图是指在同一个画布(Figure)中创建的多个独立图表,每个子图拥有自己的坐标轴(Axes)、标题、标签等元素,可独立设置样式和数据,共享画布的整体布局空间。其核心作用包括:

  • 多数据对比:同时展示不同数据系列的趋势(如同一时间段内不同产品的销量对比);
  • 多维度分析:从不同角度呈现同一数据(如原始数据、累计数据、增长率数据的联动展示);
  • 空间高效利用:在有限画布内整合多个相关图表,避免多次绘图的繁琐。

在 Matplotlib 中,子图的创建和管理是通过 FigureAxes 对象实现的:Figure 代表整个画布,Axes 则代表每个子图的坐标轴区域,一个 Figure 可以包含多个 Axes(子图)。

2. 子图布局

子图的布局决定了多个子图在画布中的排列方式,Matplotlib 支持两种主要布局模式:网格布局(规则排列)和自由布局(灵活排布),分别适用于不同的展示需求。

2.1 网格布局

网格布局是将子图按照规则的行列网格进行排列(如 2 行 3 列、1 行 2 列等),每个子图占据网格中的一个单元格,适合展示结构规整、数量固定的子图。这种布局的优势是整齐有序,便于批量创建和管理,尤其适合对比性质的多组数据展示。

常用实现方法及特点:

实现方法语法/示例核心功能适用场景优势特点
plt.subplots()fig, axes = plt.subplots(nrows=2, ncols=2)一次性创建指定行列数的网格子图,返回画布(fig)和子图数组(axes行列数固定、需批量创建子图的场景操作简洁,支持通过数组索引快速访问子图;可统一设置 sharex/sharey 共享坐标轴
plt.subplot()ax1 = plt.subplot(2, 2, 1)(2行2列网格中的第1个子图,index从1开始)逐个创建子图,通过 rows, cols, index 指定子图在网格中的位置按需创建单个子图,或动态生成网格布局灵活性高,可根据需求分步创建子图;无需提前确定所有子图数量
GridSpecpython<br>gs = plt.GridSpec(2, 2)<br>ax1 = plt.subplot(gs[0, :]) # 第1行占满2列<br>自定义网格行列跨度,支持子图合并单元格(如跨多行/多列)复杂网格布局(如部分子图需占据更大空间)支持非均匀布局,可精确控制子图尺寸和位置;适合突出重要子图的场景
网格布局整体特点
1. 子图位置由行数(nrows)和列数(ncols)严格定义,排列整齐有序;
2. 支持通过 sharex(共享x轴)、sharey(共享y轴)减少重复坐标轴标签,提升可读性;
3. 适合子图数量固定、需要统一风格的场景(如论文中的多组实验结果对比、同一指标的多维度分析)。

2.2 自由布局

自由布局允许子图在画布中按照自定义的位置和大小进行排布,不受网格行列的限制,适合展示结构不规则或需要突出某个子图的场景。这种布局的优势是灵活性高,可根据子图的重要性调整大小和位置,突出核心信息。

常用实现方法及特点:

实现方法核心功能语法/示例参数说明([left, bottom, width, height]适用场景
plt.axes()通过相对坐标和尺寸创建子图,直接关联当前画布ax1 = plt.axes([0.1, 0.1, 0.4, 0.4])- left:子图左边缘距画布左边界的相对距离(0-1)
- bottom:子图下边缘距画布下边界的相对距离(0-1)
- width:子图宽度占画布的比例(0-1)
- height:子图高度占画布的比例(0-1)
快速创建单个自由布局子图,脚本式编程场景
Figure.add_axes()通过画布对象添加子图,需先创建画布,适合面向对象编程python<br>fig = plt.figure()<br>ax2 = fig.add_axes([0.6, 0.1, 0.3, 0.7])<br>plt.axes() 参数完全一致,参数含义同上多画布管理,需明确关联子图所属画布的场景
自由布局的整体特点
1. 子图位置和大小完全自定义,支持重叠、嵌套、非对称排布等灵活效果;
2. 无需遵循网格规则,可根据子图重要性调整尺寸(如核心图表放大,辅助图表缩小);
3. 需手动优化参数避免子图重叠或间距失衡,对布局设计经验要求较高。

二、绘制等分区域子图

等分区域子图是指将画布按照固定行列数均匀分割,每个子图占据相同大小的网格空间,适合需要平等展示多组相关数据的场景。以下分别介绍两种常用的绘制方法:plt.subplot()plt.subplots()

1. 使用 plt.subplot() 绘制子图

plt.subplot() 是 Matplotlib 中创建网格子图的基础方法,通过指定网格的行数、列数和子图索引,逐个创建子图。该方法灵活度高,可按需创建单个或多个子图,适合动态生成子图的场景。

plt.subplot() 方法参数说明:

参数名作用描述取值示例补充说明
nrows网格的行数23决定子图布局的行数,如 nrows=2 表示将画布分为 2 行
ncols网格的列数24决定子图布局的列数,如 ncols=3 表示将画布分为 3 列
index子图在网格中的索引位置15索引从 1 开始,按“行优先”排序(如 2x2 网格的索引顺序为 1→2→3→4)
projection子图的投影类型'polar'可选参数,用于创建特殊投影子图(如极坐标图),默认为笛卡尔坐标系
polar是否使用极坐标系(简化的 projectionTrueFalse等价于 projection='polar',优先级低于 projection
sharex与其他子图共享 x 轴ax 对象sharex=ax1 表示与 ax1 子图共享 x 轴,减少重复标签
sharey与其他子图共享 y 轴ax 对象sharey=ax2 表示与 ax2 子图共享 y 轴

示例:绘制多个子图

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,使用其数值计算功能
import numpy as np# 使用 numpy 的 linspace 函数生成一个从 0 到 10 的等差数列,共 100 个点
x = np.linspace(0, 10, 100)# 创建一个大小为 (宽度10英寸, 高度8英寸) 的画布(Figure)
plt.figure(figsize=(10, 8))# 在画布上创建第一个子图(2行2列中的第1个位置)
# subplot(2, 2, 1) 表示将画布分为2行2列共4个子图,当前操作的是第1个子图
plt.subplot(2, 2, 1)
# 在该子图中绘制 sin(x) 曲线,颜色设置为蓝色
plt.plot(x, np.sin(x), color='blue')
# 设置该子图的标题为 'sin(x)'
plt.title('sin(x)')# 在画布上创建第二个子图(2行2列中的第2个位置)
plt.subplot(2, 2, 2)
# 在该子图中绘制 cos(x) 曲线,颜色设置为红色
plt.plot(x, np.cos(x), color='red')
# 设置该子图的标题为 'cos(x)'
plt.title('cos(x)')# 在画布上创建第三个子图(2行2列中的第3个位置)
plt.subplot(2, 2, 3)
# 在该子图中绘制 tan(x) 曲线,颜色设置为绿色
plt.plot(x, np.tan(x), color='green')
# 设置该子图的标题为 'tan(x)'
plt.title('tan(x)')# 在画布上创建第四个子图(2行2列中的第4个位置)
plt.subplot(2, 2, 4)
# 在该子图中绘制 exp(x/10) 曲线,颜色设置为紫色
plt.plot(x, np.exp(x/10), color='purple')
# 设置该子图的标题为 'exp(x/10)'
plt.title('exp(x/10)')# 调用 tight_layout 函数自动调整子图之间的间距,避免重叠或过于紧凑
plt.tight_layout()# 显示整个画布上的所有子图
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

示例:工业月度同比情况

数据如下图所示,需要根据这个数据绘制多个子图。

在这里插入图片描述

实现代码如下所示:

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 pandas 模块,用于读取和处理 CSV 数据
import pandas as pd# 设置中文字体为 SimHei(黑体),确保图表中的中文标签(如标题、坐标轴)能正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']# 解决负号 '-' 显示为方块的问题(默认字体可能不支持负号)
# 设置为 False 表示允许正常显示负号
plt.rcParams['axes.unicode_minus'] = False# 定义 CSV 文件路径,请根据实际情况替换为你的文件路径
csv_file_path = './data/工业月度同比情况.csv'# 使用 pandas 读取指定路径的 CSV 文件,返回一个 DataFrame 对象
df = pd.read_csv(csv_file_path)# 从 DataFrame 中提取“月份”列,并转换为 Python 列表,用于后续绘图的 x 轴数据
month = df['月份'].tolist()# 提取“规模以上工业同比增速(%)”列数据,转换为列表
industry_speed = df['规模以上工业同比增速(%)'].tolist()# 提取“钢材同比增速(%)”列数据,转换为列表
steel_speed = df['钢材同比增速(%)'].tolist()# 提取“十种有色金属同比增速(%)”列数据,转换为列表
metals_speed = df['十种有色金属同比增速(%)'].tolist()# 创建第一个子图:位于 3 行 1 列布局中的第 1 个位置
plt.subplot(3, 1, 1)
# 绘制折线图:x 轴为 month,y 轴为 industry_speed
# 颜色为红色,数据点用圆形标记(marker='o'),标记大小为 3
plt.plot(month, industry_speed, color='red', marker='o', markersize=3)
# 设置该子图的标题
plt.title('规模以上工业同比增速')
# 设置 y 轴标签
plt.ylabel('增长速度(%)')
# 设置 y 轴的数值范围为 0 到 10,便于统一尺度观察趋势
plt.ylim(0, 10)
# 在每个数据点上方添加文本标签,显示具体数值
for i in range(len(df)):plt.text(month[i],  # x 坐标:对应月份industry_speed[i],  # y 坐标:对应增速值s=industry_speed[i],  # 显示的文本内容:增速数值ha='center',  # 水平对齐方式:居中对齐va='bottom'  # 垂直对齐方式:文本在点的下方(向上显示))# 创建第二个子图:位于 3 行 1 列布局中的第 2 个位置
plt.subplot(3, 1, 2)
# 绘制钢材增速折线图,颜色为绿色
plt.plot(month, steel_speed, color='green', marker='o', markersize=3)
plt.title('钢材同比增长速度')
plt.ylabel('增长速度(%)')
# 设置 y 轴范围:从 -5 到 20,因为钢材增速可能出现负值
plt.ylim(-5, 20)
# 为每个数据点添加数值标签
for i in range(len(df)):plt.text(month[i],steel_speed[i],s=steel_speed[i],ha='center',va='bottom')# 创建第三个子图:位于 3 行 1 列布局中的第 3 个位置
plt.subplot(3, 1, 3)
# 绘制十种有色金属增速折线图,颜色为蓝色
plt.plot(month, metals_speed, color='blue', marker='o', markersize=3)
plt.title('十种有色金属同比增长速度')
plt.ylabel('增长速度(%)')
# 设置 y 轴范围:0 到 15
plt.ylim(0, 15)
# 为每个数据点添加数值标签
for i in range(len(df)):plt.text(month[i],metals_speed[i],s=metals_speed[i],ha='center',va='bottom')# 自动调整子图之间的间距,防止标题、标签等元素重叠
plt.tight_layout()# 显示绘制好的图形窗口
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

2. 使用 plt.subplots() 绘制子图

plt.subplots() 是创建网格子图的高效方法,一次性创建指定行列数的所有子图,并返回画布(Figure)和子图数组(Axes)。该方法适合批量创建结构固定的子图,代码更简洁,便于统一管理。

plt.subplots() 方法参数说明:

参数名作用描述取值示例补充说明
nrows网格的行数(默认 1)23nrows=2 表示创建 2 行子图
ncols网格的列数(默认 1)24ncols=3 表示创建 3 列子图
figsize画布的尺寸(宽, 高),单位为英寸(10, 8)控制整体画布大小,影响所有子图的显示比例
dpi画布的分辨率(每英寸像素数)100150默认值为 100,数值越大图像越清晰
sharex子图是否共享 x 轴True'col'True/'all' 表示所有子图共享;'col' 表示每列子图共享;False 不共享
sharey子图是否共享 y 轴True'row'True/'all' 表示所有子图共享;'row' 表示每行子图共享;False 不共享
hspace子图之间的垂直间距(相对高度比例)0.30.5默认值为 0.2,数值越大间距越宽
wspace子图之间的水平间距(相对宽度比例)0.30.5默认值为 0.2,数值越大间距越宽
subplot_kw传递给子图的关键字参数(如 projection{'projection': 'polar'}用于为所有子图统一设置属性(如都使用极坐标)

示例:绘制多个子图

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,使用其数值计算功能
import numpy as np# 使用 numpy 的 linspace 函数生成一个从 0 到 10 的等差数列,共 100 个点,作为 x 轴的数据
x = np.linspace(0, 10, 100)# 创建一个包含 2 行 2 列(共 4 个)子图的网格,并返回图形对象 fig 和子图数组 axes
# 注意:这里的 nrows=2 和 ncols=2 实际创建的是 2 行 2 列的布局,但代码注释中提到的是 2 行 3 列,可能是注释错误
fig, axes = plt.subplots(nrows=2, ncols=2)# 第 1 行第 1 列位置的子图绘制 sin(x) 曲线,颜色设置为蓝色
axes[0, 0].plot(x, np.sin(x), color='blue')
axes[0, 0].set_title('sin(x)')  # 设置该子图标题为 'sin(x)'# 第 1 行第 2 列位置的子图绘制 cos(x) 曲线,颜色设置为紫色
axes[0, 1].plot(x, np.cos(x), color='purple')
axes[0, 1].set_title('cos(x)')  # 设置该子图标题为 'cos(x)'# 第 2 行第 1 列位置的子图绘制 tan(x) 曲线,颜色设置为橙色
axes[1, 0].plot(x, np.tan(x), color='orange')
axes[1, 0].set_title('tan(x)')  # 设置该子图标题为 'tan(x)'# 第 2 行第 2 列位置的子图绘制 exp(x/10) 曲线,颜色设置为棕色
axes[1, 1].plot(x, np.exp(x / 10), color='brown')
axes[1, 1].set_title('exp(x/10)')  # 设置该子图标题为 'exp(x/10)'# 调用 tight_layout 函数自动调整子图之间的间距,避免重叠或过于紧凑
plt.tight_layout()# 显示整个画布上的所有子图
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

示例:部分国家养猫与养狗人群比例

数据如下图所示,需要根据这个数据绘制多个子图。

在这里插入图片描述

实现代码如下所示:

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,用于数值计算和数组操作
import numpy as np
# 导入 pandas 模块,用于读取和处理 CSV 数据
import pandas as pd# 设置中文字体为 SimHei(黑体),确保图表中的中文标签(如标题、坐标轴、图例)能正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']# 解决负号 '-' 显示为方块的问题(某些中文字体不支持负号)
# 设置为 False 表示允许正常显示负号
plt.rcParams['axes.unicode_minus'] = False# 定义 CSV 文件路径,请根据实际情况替换为你的实际文件路径
csv_file_path = './data/部分国家养猫与养狗人群比例.csv'# 使用 pandas 读取指定路径的 CSV 文件,返回一个 DataFrame 对象(二维表格结构)
df = pd.read_csv(csv_file_path)# 从 DataFrame 中提取“国家”列,并转换为 Python 列表
# 用于后续作为条形图的 y 轴标签(国家名称)
country = df['国家'].tolist()# 提取“养猫人群比例(%)”列数据,转换为列表
# 用于绘制养猫比例的横向条形图
x_cat = df['养猫人群比例(%)'].tolist()# 提取“养狗人群比例(%)”列数据,转换为列表
# 用于绘制养狗比例的横向条形图
x_dog = df['养狗人群比例(%)'].tolist()# 创建一个包含 1 行 2 列子图的图形画布
# fig: 整个图形对象,用于控制整体布局
# ax: 包含两个 Axes 对象的数组,分别对应左右两个子图
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 6))  # 可选:设置画布大小# 绘制左侧子图:养猫人群比例的横向条形图(barh 表示 horizontal bar)
ax[0].barh(y=np.arange(len(country)),  # y 轴位置:用 0,1,2... 表示每个国家的位置width=x_cat,  # 条形的长度(宽度),对应养猫比例数值height=0.5,  # 条形的高度(厚度),可调整美观度tick_label=country,  # y 轴刻度标签,显示国家名称color='#ffa2a5'  # 条形颜色,使用十六进制浅红色调(粉红色)
)
ax[0].set_title('部分国家养猫人群比例')  # 设置左侧子图标题
ax[0].set_xlabel('人群比例(%)')  # 设置 x 轴标签
# 为左侧子图的每个条形添加数值标签
for i in range(len(country)):ax[0].text(x=x_cat[i], y=i, s=f'{i}%', ha='left', va='center')# 绘制右侧子图:养狗人群比例的横向条形图
ax[1].barh(y=np.arange(len(country)),  # y 轴位置与左侧一致,确保国家对齐width=x_dog,  # 条形长度对应养狗比例height=0.5,  # 条形高度tick_label=country,  # 显示国家名称color='#a2d5f5'  # 条形颜色,使用十六进制浅蓝色调
)
ax[1].set_title('部分国家养狗人群比例')  # 设置右侧子图标题
ax[1].set_xlabel('人群比例(%)')  # 设置 x 轴标签
# 为右侧子图的每个条形添加数值标签
for i in range(len(country)):ax[1].text(x=x_dog[i], y=i, s=f'{i}%', ha='left', va='center')# 自动调整子图之间的间距,防止标题、标签等元素重叠或显示不全
plt.tight_layout()# 显示绘制好的图形窗口
plt.show()

绘制的图形如下图所示:

在这里插入图片描述


三、绘制跨越区域子图

1. 使用 plt.subplot2grid() 绘制子图

plt.subplot2grid() 允许将画布划分为一个二维网格,并通过指定起始位置和跨越范围来创建子图,非常适合制作复杂布局的可视化面板(如仪表盘)。

plt.subplot2grid()方法参数说明:

参数名类型描述示例
shapetuple (rows, cols)定义整个画布被划分为多少行和列的网格(3, 3) 表示 3 行 3 列
loctuple (row, col)指定子图左上角所在的网格位置(从 (0,0) 开始)(0, 0) 表示第一行第一列
rowspanint(可选)子图纵向跨越的行数2 表示占两行高度
colspanint(可选)子图横向跨越的列数2 表示占两列宽度
**kwargs其他参数传递给 Axes 的参数,如 figsize、投影方式等projection='polar'

2. 示例:抖音和快手用户画像对比

数据如下图所示,需要根据这两个数据绘制跨区域子图。

在这里插入图片描述

实现代码如下所示:

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,用于数值计算和数组操作(例如生成坐标位置)
import numpy as np
# 导入 pandas 模块,用于读取和处理 CSV 数据
import pandas as pd# 设置中文字体为 SimHei(黑体),确保图表中的中文标签(如标题、坐标轴、图例)能正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']# 解决负号 '-' 显示为方块的问题(某些中文字体不支持负号)
# 设置为 False 表示允许正常显示负号
plt.rcParams['axes.unicode_minus'] = False# 定义两个 CSV 文件的路径,请根据实际情况替换为你的实际文件路径
csv_file_path1 = './data/抖音和快手平台用户城市分布.csv'  # 用户城市分布数据
csv_file_path2 = './data/抖音和快手平台用户年龄分布.csv'  # 用户年龄分布数据# 使用 pandas 读取两个 CSV 文件,返回两个 DataFrame 对象(二维表格结构)
df1 = pd.read_csv(csv_file_path1)  # 城市分布数据
df2 = pd.read_csv(csv_file_path2)  # 年龄分布数据# 为城市分布图生成 x 轴的位置索引(0, 1, 2...),用于控制柱子的水平位置
x1 = np.arange(len(df1))
# 为年龄分布图生成 y 轴的位置索引(0, 1, 2...),用于控制条形的垂直位置
x2 = np.arange(len(df2))# 提取城市分类标签(如:一线城市、二线城市等),用于 x 轴刻度标签
city_labels = df1['城市分类'].tolist()
# 提取年龄区间标签(如:18-24岁、25-34岁等),用于 y 轴刻度标签
age_labels = df2['年龄区间'].tolist()# 提取抖音平台在不同城市的用户比例数据
douyin_data1 = df1['抖音用户比例(%)'].tolist()
# 提取快手平台在不同城市的用户比例数据
kuaishou_data1 = df1['快手用户比例(%)'].tolist()# 提取抖音平台在不同年龄区间的用户比例数据
douyin_data2 = df2['抖音用户比例(%)'].tolist()
# 提取快手平台在不同年龄区间的用户比例数据
kuaishou_data2 = df2['快手用户比例(%)'].tolist()# -------------------------------
# 第一个子图:城市分布对比(顶部横跨两列)
# 使用 subplot2grid 创建自定义布局:整个画布划分为 3 行 2 列
# 当前子图从 (0,0) 开始(第1行第1列),横向占2列,纵向占1行
ax1 = plt.subplot2grid((3, 2), (0, 0), rowspan=1, colspan=2)# 绘制抖音用户比例的柱状图
ax1.bar(x=x1,  # 柱子的 x 坐标位置height=douyin_data1,  # 柱子的高度(用户比例)color='#a2c4ff',  # 颜色:浅蓝色(代表抖音)tick_label=city_labels,  # x 轴刻度标签:城市分类名称width=0.3,  # 柱子宽度label='抖音'  # 图例标签
)# 绘制快手用户比例的柱状图,x 位置向右偏移 0.3,实现并列显示
ax1.bar(x=x1 + 0.3,  # 向右偏移,避免与抖音柱子重叠height=kuaishou_data1,  # 快手用户比例color='#ffa2c4',  # 颜色:浅粉色(代表快手)tick_label=city_labels,  # 标签与抖音一致width=0.3,  # 柱子宽度label='快手'  # 图例标签
)# 设置标题
ax1.set_title('抖音和快手平台用户城市分布')
# 设置 x 轴标签
ax1.set_xlabel('城市分类')
# 设置 y 轴标签
ax1.set_ylabel('用户比例(%)')
# 添加图例,设置字体大小为 8
ax1.legend(fontsize=8)
# 设置 y 轴范围为 0 到 25%,便于统一比较
ax1.set_ylim(0, 25)# 在每个柱子顶部添加数值标签(抖音)
for i in range(len(df1)):ax1.text(x=x1[i],  # x 位置y=douyin_data1[i],  # y 位置(柱子顶部)s=douyin_data1[i],  # 显示的文本内容ha='center',  # 水平居中对齐va='bottom'  # 垂直底部对齐(在柱子上方))# 添加快手数据标签ax1.text(x=x1[i] + 0.3,y=kuaishou_data1[i],s=kuaishou_data1[i],ha='center',va='bottom')# -------------------------------
# 第二个子图:抖音平台用户年龄分布(左下角)
# 位置:从 (1,0) 开始(第2行第1列),纵向占2行,横向占1列
ax2 = plt.subplot2grid((3, 2), (1, 0), rowspan=2, colspan=1)# 绘制横向条形图(barh),展示抖音用户在各年龄段的比例
ax2.barh(y=x2,  # 条形的 y 位置width=douyin_data2,  # 条形长度(用户比例)height=0.5,  # 条形高度(厚度)tick_label=age_labels,  # y 轴标签:年龄区间color='#a2c4ff'  # 浅蓝色,与上图一致
)# 设置标题
ax2.set_title('抖音平台用户年龄分布')
# 设置 x 轴标签
ax2.set_xlabel('用户比例(%)')
# 设置 x 轴范围为 0 到 30%,便于比较
ax2.set_xlim(0, 30)# 在每个条形右侧添加数值标签
for i in range(len(df2)):ax2.text(x=douyin_data2[i],  # x 位置:比例值y=x2[i],  # y 位置:对应年龄区间s=douyin_data2[i],  # 显示的数值ha='left',  # 水平左对齐(在条形右侧)va='center'  # 垂直居中对齐)# -------------------------------
# 第三个子图:快手平台用户年龄分布(右下角)
# 位置:从 (1,1) 开始(第2行第2列),纵向占2行,横向占1列
ax3 = plt.subplot2grid((3, 2), (1, 1), rowspan=2, colspan=1)# 绘制横向条形图,展示快手用户在各年龄段的比例
ax3.barh(y=x2,width=kuaishou_data2,height=0.5,tick_label=age_labels,color='#ffa2c4'  # 浅粉色,与上图一致
)# 设置标题
ax3.set_title('快手平台用户年龄分布')
# 设置 x 轴标签
ax3.set_xlabel('用户比例(%)')
# 设置 x 轴范围一致,便于对比
ax3.set_xlim(0, 30)# 在每个条形右侧添加数值标签
for i in range(len(df2)):ax3.text(x=kuaishou_data2[i],y=x2[i],s=kuaishou_data2[i],ha='left',va='center')# 自动调整所有子图之间的间距,防止标题、标签、图例等元素重叠或被截断
plt.tight_layout()# 显示绘制好的图形窗口
plt.show()

绘制的图形如下图所示:

在这里插入图片描述


四、绘制自定义区域子图

在 Matplotlib 中,除了使用 subplot()subplot2grid() 创建规则布局外,还可以通过更灵活的机制实现高度自定义的子图区域划分。本节将介绍如何使用 GridSpec 类和 add_gridspec() 方法来创建复杂的、可定制间距与比例的子图布局。

1. 通过 GridSpec 类绘制

GridSpec 是一个用于定义网格布局的类,可以指定行数、列数以及每行/列的尺寸比例和间距。

GridSpec 类构造方法参数说明:

参数名类型描述示例
nrowsint网格的行数3
ncolsint网格的列数2
figureFigure(可选)关联的画布对象fig
left, right, top, bottomfloat(可选)子图区域距离画布边缘的位置(归一化坐标 0~1)left=0.1, right=0.9
wspacefloat(可选)列之间的水平间距0.3
hspacefloat(可选)行之间的垂直间距0.4
width_ratioslist of floats每列的相对宽度比例[2, 1] 表示第一列是第二列的两倍宽
height_ratioslist of floats每行的相对高度比例[1, 3] 表示第二行是第一行的三倍高

🔹 所有间距值为 None 时表示自动调整(默认);
🔹 width_ratiosheight_ratios 使用比例而非绝对值。

示例:使用 GridSpec 创建布局

# 导入 matplotlib.gridspec 模块,用于创建复杂的、可自定义行列比例的子图网格布局
import matplotlib.gridspec as gridspec
# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt# 创建一个画布(Figure),设置图形大小为 8 英寸宽 × 6 英寸高
fig = plt.figure(figsize=(8, 6))# 使用 GridSpec 定义一个 3 行 3 列的网格布局(共 9 个单元格)
# 该布局将用于在画布上精确控制每个子图的位置和大小
gs = gridspec.GridSpec(nrows=3,  # 网格的行数:3 行ncols=3,  # 网格的列数:3 列figure=fig,  # 指定该 GridSpec 属于哪个画布对象wspace=0.2,  # 子图之间的横向间距(空白宽度比例),0.2 表示中等间距hspace=0.2,  # 子图之间的纵向间距(空白高度比例)width_ratios=[1, 1, 1],  # 每一列的相对宽度比例:三列等宽height_ratios=[1, 1, 1]  # 每一行的相对高度比例:三行等高
)# 在网格的第 1 行(索引 0),占据所有 3 列(切片 0:3)创建第一个子图
ax1 = fig.add_subplot(gs[0, 0:3])
# 在 ax1 中绘制一条简单的折线(x: 0~4, y: [1,2,3,4,5])
ax1.plot([1, 2, 3, 4, 5])# 在网格的第 2 行(索引 1),占据前 2 列(0~1列)创建第二个子图
ax2 = fig.add_subplot(gs[1, 0:2])
ax2.plot([1, 2, 3, 4, 5])# 在网格的第 3 行(索引 2),占据第 1 列(索引 0)创建第三个子图
ax3 = fig.add_subplot(gs[2, :1])  # 等价于 gs[2, 0]
ax3.plot([1, 2, 3, 4, 5])# 在网格的第 3 行(索引 2),占据第 2 列(索引 1)创建第四个子图
ax4 = fig.add_subplot(gs[2, 1:2])  # 注意:切片 1:2 表示只取第1列(索引1)
ax4.plot([1, 2, 3, 4, 5])# 在网格的第 2-3 行(索引 1 到 2),占据第 3 列(索引 2)创建第五个子图
# 这是一个跨行的子图(纵向合并两个单元格)
ax5 = fig.add_subplot(gs[1:3, 2])
ax5.plot([1, 2, 3, 4, 5])# 显示图形
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

2. 通过 add_gridspec() 方法绘制

Figure.add_gridspec() 是 Matplotlib 3.1+ 推荐的现代方法,它直接在画布上创建一个 GridSpec 实例,并返回该对象,便于链式调用。

add_gridspec()方法参数说明:

参数名类型描述示例
nrowsint行数2
ncolsint列数3
left, right, top, bottomfloat子图区域边界(归一化坐标)left=0.1
wspace, hspacefloat水平/垂直间距wspace=0.2
width_ratioslist各列宽度比例[1, 2, 1]
height_ratioslist各行高度比例[3, 1]

示例:使用 add_gridspec() 创建布局

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt# 创建一个图形画布(Figure),并设置其大小为 8 英寸宽 × 6 英寸高
# figsize 参数控制整个图形的尺寸,便于后续排版和展示
fig = plt.figure(figsize=(8, 6))# 在画布 fig 上添加一个 GridSpec(网格规范)对象,用于定义子图的网格布局
# 这种方式比直接使用 gridspec.GridSpec 更简洁,是 matplotlib 推荐的现代写法
gs = fig.add_gridspec(nrows=3,  # 定义网格有 3 行ncols=3,  # 定义网格有 3 列figure=fig,  # 指定该 GridSpec 所属的画布对象(通常可省略,因为是通过 fig 调用的)wspace=0.2,  # 设置子图之间的横向间距(width space)hspace=0.2,  # 设置子图之间的纵向间距(height space)width_ratios=[1, 1, 1],  # 每一列的相对宽度比例height_ratios=[1, 1, 1]  # 每一行的相对高度比例
)# 在网格的第 1 行(索引 0),占据所有 3 列(切片 0:3)创建第一个子图
ax1 = fig.add_subplot(gs[0, 0:3])
# 在 ax1 中绘制一条简单的折线(x: 0~4, y: [1,2,3,4,5])
ax1.plot([1, 2, 3, 4, 5])# 在网格的第 2 行(索引 1),占据前 2 列(0~1列)创建第二个子图
ax2 = fig.add_subplot(gs[1, 0:2])
ax2.plot([1, 2, 3, 4, 5])# 在网格的第 3 行(索引 2),占据第 1 列(索引 0)创建第三个子图
ax3 = fig.add_subplot(gs[2, :1])  # 等价于 gs[2, 0]
ax3.plot([1, 2, 3, 4, 5])# 在网格的第 3 行(索引 2),占据第 2 列(索引 1)创建第四个子图
ax4 = fig.add_subplot(gs[2, 1:2])  # 注意:切片 1:2 表示只取第1列(索引1)
ax4.plot([1, 2, 3, 4, 5])# 在网格的第 2-3 行(索引 1 到 2),占据第 3 列(索引 2)创建第五个子图
# 这是一个跨行的子图(纵向合并两个单元格)
ax5 = fig.add_subplot(gs[1:3, 2])
ax5.plot([1, 2, 3, 4, 5])# 显示图形
plt.show()

绘制的图形如下图所示:

在这里插入图片描述


五、子图坐标轴共享

在创建多个子图时,有时候需要共享某些坐标轴(x轴或y轴)以便于比较不同数据集的趋势或分布。Matplotlib 提供了便捷的方法来实现这一点,即通过 plt.subplot()plt.subplots() 中的 sharexsharey 参数来控制坐标轴共享。

1. 共享相邻子图的坐标轴

1.1 共享相邻子图的坐标轴介绍

共享坐标轴能够确保相关子图之间的一致性,这对于比较不同的数据集尤其有用。例如,在时间序列分析中,可能希望所有子图共享相同的x轴以展示不同变量随时间的变化趋势;或者在散点图矩阵中,每个子图都共享相同的x轴和y轴范围,以便于对比不同变量之间的关系。

共享坐标轴不仅可以减少重复工作,还能提高图形的可读性和一致性。此外,当调整一个共享坐标轴的缩放比例或移动视图窗口时,其他共享该坐标轴的子图也会同步更新,增强了交互式探索数据的能力。

1.2 plt.subplot()plt.subplots() 方法中的参数 sharexsharey 的取值

在 Matplotlib 中,plt.subplot()plt.subplots() 方法允许通过设置 sharexsharey 参数来控制坐标轴的共享方式。以下是这些参数可能的取值及其含义:

参数 sharexsharey 的取值说明:

取值描述
"none"不共享任何坐标轴(默认)。
"all"所有子图共享同一个x轴或y轴。这意味着所有子图都将具有相同的轴刻度和范围。
"row"同一行中的子图共享x轴或y轴。适用于需要在同一行内进行直接比较的情况。
"col"同一列中的子图共享x轴或y轴。适用于需要在同一列内进行直接比较的情况。
"auto"根据布局自动决定是否共享坐标轴。通常不会主动选择此选项,因为它依赖于具体的上下文。

1.3 示例:部分国家养猫与养狗人群比例

数据如下图所示,需要根据这个数据绘制多个子图,并共享y轴。

在这里插入图片描述

实现代码如下所示:

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,用于数值计算和数组操作
import numpy as np
# 导入 pandas 模块,用于读取和处理 CSV 数据
import pandas as pd# 设置中文字体为 SimHei(黑体),确保图表中的中文标签(如标题、坐标轴、图例)能正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']# 解决负号 '-' 显示为方块的问题(某些中文字体不支持负号)
# 设置为 False 表示允许正常显示负号
plt.rcParams['axes.unicode_minus'] = False# 定义 CSV 文件路径,请根据实际情况替换为你的实际文件路径
csv_file_path = './data/部分国家养猫与养狗人群比例.csv'# 使用 pandas 读取指定路径的 CSV 文件,返回一个 DataFrame 对象(二维表格结构)
df = pd.read_csv(csv_file_path)# 从 DataFrame 中提取“国家”列,并转换为 Python 列表
# 用于后续作为条形图的 y 轴标签(国家名称)
country = df['国家'].tolist()# 提取“养猫人群比例(%)”列数据,转换为列表
# 用于绘制养猫比例的横向条形图
x_cat = df['养猫人群比例(%)'].tolist()# 提取“养狗人群比例(%)”列数据,转换为列表
# 用于绘制养狗比例的横向条形图
x_dog = df['养狗人群比例(%)'].tolist()# 创建一个包含 1 行 2 列子图的图形画布
# fig: 整个图形对象,用于控制整体布局
# ax: 包含两个 Axes 对象的数组,分别对应左右两个子图
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 6), sharey='row')# 绘制左侧子图:养猫人群比例的横向条形图(barh 表示 horizontal bar)
ax[0].barh(y=np.arange(len(country)),  # y 轴位置:用 0,1,2... 表示每个国家的位置width=x_cat,  # 条形的长度(宽度),对应养猫比例数值height=0.5,  # 条形的高度(厚度),可调整美观度tick_label=country,  # y 轴刻度标签,显示国家名称color='#ffa2a5'  # 条形颜色,使用十六进制浅红色调(粉红色)
)
ax[0].set_title('部分国家养猫人群比例')  # 设置左侧子图标题
ax[0].set_xlabel('人群比例(%)')  # 设置 x 轴标签
# 为左侧子图的每个条形添加数值标签
for i in range(len(country)):ax[0].text(x=x_cat[i], y=i, s=f'{i}%', ha='left', va='center')# 绘制右侧子图:养狗人群比例的横向条形图
ax[1].barh(y=np.arange(len(country)),  # y 轴位置与左侧一致,确保国家对齐width=x_dog,  # 条形长度对应养狗比例height=0.5,  # 条形高度tick_label=country,  # 显示国家名称color='#a2d5f5'  # 条形颜色,使用十六进制浅蓝色调
)
ax[1].set_title('部分国家养狗人群比例')  # 设置右侧子图标题
ax[1].set_xlabel('人群比例(%)')  # 设置 x 轴标签
# 为右侧子图的每个条形添加数值标签
for i in range(len(country)):ax[1].text(x=x_dog[i], y=i, s=f'{i}%', ha='left', va='center')# 自动调整子图之间的间距,防止标题、标签等元素重叠或显示不全
plt.tight_layout()# 显示绘制好的图形窗口
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

2. 共享非相邻子图的坐标轴

2.1 共享非相邻子图的坐标轴介绍

在 Matplotlib 中,除了共享相邻子图(如同行或同列)的坐标轴外,有时也需要让不相邻的子图(例如分散在画布不同位置的子图)共享同一个坐标轴(x 轴或 y 轴)。这种需求常见于复杂布局中,例如仪表盘、多面板可视化或需要跨区域对比数据的场景。

plt.subplots(sharex=..., sharey=...) 仅适用于规则网格布局不同,共享非相邻子图的坐标轴通常需要通过手动指定 sharexsharey 参数,将一个子图(Axes)作为另一个子图的“参考轴”,从而实现坐标轴的联动。

2.2 示例:非相邻子图坐标轴共享

# 导入必要的库
import matplotlib.pyplot as plt
import numpy as np# 使用 subplot 函数创建一个 2x2 的网格布局中的第一个子图 (即左上角位置)
# 221 表示在 2 行 2 列的网格中的第 1 个位置
ax_one = plt.subplot(221)# 生成 x 轴数据,范围从 0 到 2π,共 400 个点
x1 = np.linspace(0, 2 * np.pi, 400)
# 根据 x1 计算 y 轴数据,这里使用 cos(x^2) 函数
y1 = np.cos(x1 ** 2)# 在 ax_one 子图中绘制曲线
ax_one.plot(x1, y1)# 生成第二个 x 轴的数据集,范围从 0.01 到 10,共 100 个点
x2 = np.linspace(0.01, 10, 100)
# 根据 x2 计算 y 轴数据,这里使用 sin(x) 函数
y2 = np.sin(x2)# 创建 2x2 网格布局中的第四个子图 (即右下角位置),并指定与 ax_one 共享 x 轴
# 这意味着 ax_two 将具有与 ax_one 相同的 x 轴缩放和范围
ax_two = plt.subplot(224, sharex=ax_one)# 在 ax_two 子图中绘制曲线
ax_two.plot(x2, y2)# 显示图形
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

3. 同一子图共享坐标轴(双 Y 轴)

3.1 同一子图共享 x 坐标轴介绍

在 Matplotlib 中,“同一子图共享 x 坐标轴” 实际上是指:在同一个图表区域(Axes)中,创建两个独立的 Y 轴(左和右),但共享同一个 X 轴。这种技术通常被称为 “双 Y 轴图”(Dual Y-axis Plot),是数据可视化中非常常见的需求。

可使用ax.twinx()方法实现同一子图共享 x 坐标轴。

方法描述返回值是否有参数
ax.twinx()创建一个共享 x 轴、但拥有独立 y 轴 的新坐标系(通常在右侧)新的 Axes 对象❌ 无参数

3.2 示例:某地区全年气温与降水量、蒸发量的关系

数据如下图所示,需要根据这个数据绘制双y轴的图形。

在这里插入图片描述

实现代码如下所示:

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,用于数值计算和数组操作
import numpy as np
# 导入 pandas 模块,用于读取和处理 CSV 数据
import pandas as pd# 设置中文字体为 SimHei(黑体),确保图表中的中文标签(如标题、坐标轴、图例)能正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']# 解决负号 '-' 显示为方块的问题(某些中文字体不支持负号)
# 设置为 False 表示允许正常显示负号
plt.rcParams['axes.unicode_minus'] = False# 定义 CSV 文件路径,请根据实际情况替换为你的实际文件路径
csv_file_path = './data/某地区全年的平均气温与降水量、蒸发量 .csv'# 使用 pandas 读取指定路径的 CSV 文件,返回一个 DataFrame 对象(二维表格结构)
df = pd.read_csv(csv_file_path)# 从 DataFrame 中提取 '月份' 列,并将其转换为 Python 列表
month = df['月份'].tolist()# 从 DataFrame 中提取 '蒸发量 (ml)' 列,并将其转换为 Python 列表
evaporation = df['蒸发量 (ml)'].tolist()# 从 DataFrame 中提取 '降水量 (ml)' 列,并将其转换为 Python 列表
rainfall = df['降水量 (ml)'].tolist()# 从 DataFrame 中提取 '平均气温 (℃)' 列,并将其转换为 Python 列表
temperature = df['平均气温 (℃)'].tolist()# 创建图形和子图对象,fig 是整个图像窗口,ax 是主图的坐标轴对象
fig, ax = plt.subplots()# 在主图上绘制蒸发量柱状图,设置宽度和颜色,并添加标签
ax.bar(x=np.arange(len(df)), height=evaporation, width=0.3, label='蒸发量', color='#ffa565', tick_label=month)
# 在主图上偏移0.3的位置绘制降水量柱状图,避免两组柱状图重叠
ax.bar(x=np.arange(len(df)) + 0.3, height=rainfall, width=0.3, label='降水量', color='#65a5ff')# 设置X轴标签为“月份”
ax.set_xlabel('月份')
# 设置Y轴标签为“水量 (ml)”表示蒸发量和降水量
ax.set_ylabel('水量 (ml)')
# 设置图表标题
ax.set_title('某地区全年的平均气温与降水量、蒸发量')# 创建一个新的坐标轴 ax_new,与原坐标轴共享X轴,用于展示平均气温数据
ax_new = ax.twinx()
# 在新坐标轴上绘制平均气温折线图,并添加标记点
ax_new.plot(month, temperature, color='#a565ff', marker='o', label='平均气温')
# 设置新坐标轴的Y轴标签为“温度 (℃)”
ax_new.set_ylabel('温度 (℃)')# 获取两个坐标轴上的图例句柄和标签,合并后一次性添加到图中,以确保所有元素都能正确显示在图例中
handles1, labels1 = ax.get_legend_handles_labels()
handles2, labels2 = ax_new.get_legend_handles_labels()
ax.legend(handles=handles1 + handles2, labels=labels1 + labels2)# 自动调整子图之间的间距,防止标题、标签等元素重叠或显示不全
plt.tight_layout()# 显示绘制好的图形窗口
plt.show()

绘制的图形如下图所示:

在这里插入图片描述


六、子图布局

1. 约束布局

在 Matplotlib 中,合理安排多个子图的布局对于提高图表的可读性和美观性至关重要。约束布局(Constrained Layout)是 Matplotlib 提供的一种自动调整子图位置以避免重叠和优化空间利用的功能。

1.1 约束布局介绍

约束布局是一种用于自动化管理子图间距和位置的方法,旨在减少手动调整子图布局的需求。它通过计算每个子图的最佳位置来确保:

  • 子图之间不会重叠;
  • 标题、标签、刻度等元素有足够空间显示,而不会被裁剪或遮挡;
  • 整体布局更加紧凑且有序。

约束布局特别适用于包含多个子图、颜色条、注释和其他复杂元素的图表。它可以帮助用户创建既美观又专业的可视化结果,无需反复试验不同的参数设置。

1.2 启用约束布局

启用约束布局非常简单,可以通过两种主要方式实现:

1.2.1 全局启用

可以在调用 plt.subplots() 或其他绘图函数之前,通过 plt.rcParams 设置全局使用约束布局。

import matplotlib.pyplot as pltplt.rcParams['figure.constrained_layout.use'] = True

这种方式将影响所有后续生成的图表,除非在特定的图表中明确禁用约束布局。

1.2.2 局部启用

也可以针对具体的图表启用约束布局,通过向 plt.subplots() 或其他类似函数传递 constrained_layout=True 参数。

import matplotlib.pyplot as pltfig, axs = plt.subplots(2, 2, constrained_layout=True)

这种方法允许对单个图表进行更精细的控制,不影响其他图表的默认行为。

1.2.3 自定义约束布局参数

除了简单的启用/禁用之外,还可以通过 constrained_layout_pads 参数进一步自定义约束布局的行为。

# 导入 matplotlib.pyplot 模块两次是不必要的,这里保留一次即可。
import matplotlib.pyplot as plt# 设置全局参数以控制图形布局和子图间距
plt.rcParams['figure.constrained_layout.use'] = True  # 启用 constrained_layout 布局管理器,自动调整子图位置避免重叠
plt.rcParams['figure.constrained_layout.w_pad'] = 0.04167  # 子图之间的最小宽度间距(相对字体大小)
plt.rcParams['figure.constrained_layout.h_pad'] = 0.04167  # 子图之间的最小高度间距(相对字体大小)
plt.rcParams['figure.constrained_layout.wspace'] = 0.02  # 相邻子图在水平方向上的间距(相对宽度的比例)
plt.rcParams['figure.constrained_layout.hspace'] = 0.02  # 相邻子图在垂直方向上的间距(相对高度的比例)# 创建一个包含 2 行 2 列子图的图形(即 4 个子图)
# 返回 fig(整个图形对象)和 axs(子图数组,形状为 2x2)
fig, axs = plt.subplots(nrows=2, ncols=2)# axs 是一个 2x2 的 NumPy 数组,包含四个 Axes 对象(即四个子图)
# 使用 axs.flat 可以将二维数组展平为一维迭代器,方便对每个子图进行统一操作
for ax in axs.flat:# 在每一个子图中绘制相同的折线图# x 坐标为 [1, 2, 3],y 坐标为 [4, 5, 6]ax.plot([1, 2, 3], [4, 5, 6])# 显示绘制好的图形窗口
plt.show()
1.2.4 示例:绘制多个子图(约束布局)

实现代码如下所示:

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,使用其数值计算功能
import numpy as np# 使用 numpy 的 linspace 函数生成一个从 0 到 10 的等差数列,共 100 个点,作为 x 轴的数据
x = np.linspace(0, 10, 100)# 创建一个包含 2 行 2 列(共 4 个)子图的网格,并返回图形对象 fig 和子图数组 axes
# 注意:这里的 nrows=2 和 ncols=2 实际创建的是 2 行 2 列的布局,但代码注释中提到的是 2 行 3 列,可能是注释错误
fig, axes = plt.subplots(nrows=2, ncols=2, constrained_layout=True)# 第 1 行第 1 列位置的子图绘制 sin(x) 曲线,颜色设置为蓝色
axes[0, 0].plot(x, np.sin(x), color='blue')
axes[0, 0].set_title('sin(x)')  # 设置该子图标题为 'sin(x)'# 第 1 行第 2 列位置的子图绘制 cos(x) 曲线,颜色设置为紫色
axes[0, 1].plot(x, np.cos(x), color='purple')
axes[0, 1].set_title('cos(x)')  # 设置该子图标题为 'cos(x)'# 第 2 行第 1 列位置的子图绘制 tan(x) 曲线,颜色设置为橙色
axes[1, 0].plot(x, np.tan(x), color='orange')
axes[1, 0].set_title('tan(x)')  # 设置该子图标题为 'tan(x)'# 第 2 行第 2 列位置的子图绘制 exp(x/10) 曲线,颜色设置为棕色
axes[1, 1].plot(x, np.exp(x / 10), color='brown')
axes[1, 1].set_title('exp(x/10)')  # 设置该子图标题为 'exp(x/10)'# 显示整个画布上的所有子图
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

2. 紧密布局

2.1 紧密布局介绍

紧密布局(Tight Layout) 是 Matplotlib 中一种自动调整子图位置和大小的机制,旨在消除子图之间的多余空白,并确保标题、标签、刻度等元素不会被裁剪或重叠。与“约束布局”(Constrained Layout)类似,tight_layout 也是一种布局优化工具,但它采用的是后处理方式:在所有绘图完成后,自动计算并调整子图的几何位置。

2.2 启用紧密布局

2.2.1 通过 tight_layout() 启用

tight_layout() 是 Matplotlib 中最常用的自动布局优化方法之一。它会自动调整子图(Axes)的位置和间距,确保标题、坐标轴标签、刻度等元素不会被裁剪或重叠,从而生成紧凑且美观的图表。

该方法在所有绘图操作完成后调用,是一种“后处理”式的布局调整机制。

调用方式:

plt.tight_layout()
# 或
fig.tight_layout()

两者功能相同,plt.tight_layout() 作用于当前图像,fig.tight_layout() 作用于指定的 Figure 对象。

tight_layout() 方法参数说明:

参数名类型默认值描述
padfloat1.08图像边缘到子图区域的最小边距(单位:英寸)。用于防止边缘元素被裁剪。
h_padfloat 或 Nonepad子图之间的垂直间距(英寸)。若为 None,使用 pad 值。
w_padfloat 或 Nonepad子图之间的水平间距(英寸)。若为 None,使用 pad 值。
recttuple (left, bottom, right, top)(0, 0, 1, 1)子图占据的归一化坐标区域(0~1),常用于为 suptitle、图例等外部元素预留空间。例如:rect=[0, 0, 1, 0.95] 表示子图只占用底部 95% 的高度,顶部留出空间。
2.2.2 使用 subplots() 或 figure() 方法中的 layout 参数

Matplotlib 3.6.0 开始,引入了新的统一布局管理参数 layout,可用于 plt.subplots()plt.figure() 中,支持多种布局策略。

语法:

plt.subplots(..., layout='tight')
# 或
plt.figure(..., layout='tight')

layout 参数可选值:

描述
None不启用自动布局(默认)。
'tight'启用 tight_layout 自动排版。
'constrained'启用 constrained_layout(推荐用于复杂图表)。
'compressed'类似 'tight',但在某些情况下更紧凑(实验性)。
2.2.3 通过 figure.autolayout 配置项启用

可以通过 Matplotlib 的全局配置参数 figure.autolayout默认启用 tight_layout,这样所有后续创建的图像都会自动应用 tight_layout,无需每次手动调用。

import matplotlib.pyplot as plt
# 全局启用 tight_layout
plt.rcParams['figure.autolayout'] = True
2.2.4 示例:绘制多个子图(紧密布局)

实现代码如下所示:

# 导入 matplotlib.pyplot 模块,用于绘图
import matplotlib.pyplot as plt
# 导入 numpy 模块,使用其数值计算功能
import numpy as np# 使用 numpy 的 linspace 函数生成一个从 0 到 10 的等差数列,共 100 个点,作为 x 轴的数据
x = np.linspace(0, 10, 100)# 创建一个包含 2 行 2 列(共 4 个)子图的网格,并返回图形对象 fig 和子图数组 axes
# 注意:这里的 nrows=2 和 ncols=2 实际创建的是 2 行 2 列的布局,但代码注释中提到的是 2 行 3 列,可能是注释错误
fig, axes = plt.subplots(nrows=2, ncols=2)# 第 1 行第 1 列位置的子图绘制 sin(x) 曲线,颜色设置为蓝色
axes[0, 0].plot(x, np.sin(x), color='blue')
axes[0, 0].set_title('sin(x)')  # 设置该子图标题为 'sin(x)'# 第 1 行第 2 列位置的子图绘制 cos(x) 曲线,颜色设置为紫色
axes[0, 1].plot(x, np.cos(x), color='purple')
axes[0, 1].set_title('cos(x)')  # 设置该子图标题为 'cos(x)'# 第 2 行第 1 列位置的子图绘制 tan(x) 曲线,颜色设置为橙色
axes[1, 0].plot(x, np.tan(x), color='orange')
axes[1, 0].set_title('tan(x)')  # 设置该子图标题为 'tan(x)'# 第 2 行第 2 列位置的子图绘制 exp(x/10) 曲线,颜色设置为棕色
axes[1, 1].plot(x, np.exp(x / 10), color='brown')
axes[1, 1].set_title('exp(x/10)')  # 设置该子图标题为 'exp(x/10)'# 调用 tight_layout 函数自动调整子图之间的间距,避免重叠或过于紧凑
plt.tight_layout(pad=2, h_pad=2, w_pad=2)# 显示整个画布上的所有子图
plt.show()

绘制的图形如下图所示:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92089.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++中互斥锁、共享锁深度解析

一&#xff0c;互斥锁互斥锁&#xff08;Mutex&#xff0c;全称 Mutual Exclusion&#xff09;是并发编程中用于保护共享资源的核心同步机制。它通过确保同一时间仅有一个线程访问临界区&#xff08;Critical Section&#xff09;&#xff0c;解决多线程环境下的数据竞争和不一…

Qt中的QWebSocket 和 QWebSocketServer详解:从协议说明到实际应用解析

前言 本篇围绕 QWebSocket 和 QWebSocketServer&#xff0c;从协议基础、通信模式、数据传输特点等方面展开&#xff0c;结合具体接口应用与实战案例进行说明。 在实时网络通信领域&#xff0c;WebSocket 技术以其独特的全双工通信能力&#xff0c;成为连接客户端与服务器的重要…

机器学习 —— 决策树

机器学习 —— 决策树&#xff08;Decision Tree&#xff09;详细介绍决策树是一种直观且易于解释的监督学习算法&#xff0c;广泛应用于分类和回归任务。它通过模拟人类决策过程&#xff0c;将复杂问题拆解为一系列简单的判断规则&#xff0c;最终形成类似 “树” 状的结构。以…

车规MCU软错误防护技术的多维度分析与优化路径

摘要&#xff1a;随着汽车电子技术的飞速发展&#xff0c;微控制单元&#xff08;MCU&#xff09;在汽车电子系统中的应用日益广泛。然而&#xff0c;大气中子诱发的单粒子效应&#xff08;SEE&#xff09;对MCU的可靠性构成了严重威胁。本文深入探讨了软错误防护技术在车规MCU…

原生微信小程序实现语音转文字搜索---同声传译

效果展示 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/23257ce3b6c149a1bb54fd8bc2a05c68.png#pic_center 注意&#xff1a;引入同声传译组件请看这篇文章 1.search.wxml <view class"search-page"><navigation-bar title"搜索" …

Wireshark安装过程缺失vc_runtimeMinimum_x64.msi文件,安装 Visual C++ Redistributable

一、我大意了 一开始是Npcap装不上。 在这个网站下的&#xff1a; Wireshark (kafan58.com) 安装程序&#xff1a; 安装过程&#xff1a; 无语死了&#xff0c;感觉被骗了......外网下的才是最正版的。 二、外网正版 下载最新的4.4.8版本Wireshark重新安装 2.1 vc_runtime…

高通平台Wi-Fi Display学习-- 调试 Wi-Fi Display 问题

4.1 调试 WFD 性能 4.1.1 通过启用调节器模式验证 WFD 当系统设为调节器模式时,设备的运行时钟将达到峰值。要在系统中启用调节器模式,应 在序列中输入以下命令: 1. adb shell stop mpdecision 2. adb shell echo 1→/sys/devices/system/cpu/cpu1/online 3. adb shell…

5G专网与SD-WAN技术融合:某饮料智能工厂网络架构深度解析

随着工业互联网的快速发展&#xff0c;制造业正从传统的生产模式向智能化、数字化方向转型。某饮料智能工厂项目创新性地引入了5G专网与SD-WAN技术&#xff0c;形成了“连接-计算-应用-安全”的全链条网络架构。本文将深入剖析这两种技术在智能工厂中的应用场景、部署架构&…

Java项目:基于SSM框架实现的公益网站管理系统【ssm+B/S架构+源码+数据库+毕业论文+答辩PPT+远程部署】

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本公益网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&#x…

向华为学习——IPD流程体系之IPD术语

第一章 IPD体系 1.1集成产品开发IPD Integrated Product Development,IPD是一种领先的、成熟的产品开发的管理思想和管理模式。它是根据大量成功的产品开发管理实践总结出来的,并被大量实践证明的高效的产品开发模式。通过IPD,可建立起基于市场和客户需求驱动的集成产品开…

落霞归雁:从自然之道到“存内计算”——用算法思维在芯片里开一条“数据高速航道”

作者 落霞归雁&#xff08;CSDN首发&#xff0c;转载请注明&#xff09; 段落一 现象&#xff1a;当“摩尔”老去&#xff0c;数据却在狂奔 过去 30 年&#xff0c;CPU 频率翻了 60 倍&#xff0c;而 DRAM 带宽只翻了 20 倍。算力与带宽的剪刀差&#xff0c;让“计算”变成“等…

StyleX:Meta推出的高性能零运行时CSS-in-JS解决方案

简介 StyleX 是由 Meta 开发的零运行时 CSS-in-JS 解决方案&#xff0c;在构建时将样式编译为静态 CSS&#xff0c;消除运行时开销。 核心特性 零运行时开销 – 构建时编译为静态 CSS类型安全 – 完整的 TypeScript 支持原子化 CSS – 自动生成原子化类名&#xff0c;最小化…

LINUX 85 SHElL if else 前瞻 实例

问题 判断用户是否存在 id user id $user变量判断vsftpd软件包被安装 rpm -q vsftpd rpm -ql vsftpd >& null[rootweb ~]# rpm -ql vsftpd >/dev/null 2>&1 您在 /var/spool/mail/root 中有邮件yum install vsftpd 内核主版本判断 uname -rcut -d[rootweb ~]#…

2025 年非关系型数据库全面指南:类型、优势

非关系型数据库的分类与特点随着数据量呈指数级增长和数据类型日益多样化&#xff0c;传统关系型数据库在处理海量非结构化数据时面临着严峻挑战。非关系型数据库&#xff08;NoSQL&#xff09;应运而生&#xff0c;它摒弃了传统关系模型的约束&#xff0c;采用更灵活的数据存储…

深度残差网络ResNet结构

Deep Residual Learning for Image Recognition&#xff0c;由Kaiming He、Xiangyu Zhang、Shaoqing Ren和Jian Sun于2016年发表在CVPR上 1512.03385 (arxiv.org)https://arxiv.org/pdf/1512.03385 下图中&#xff0c;左侧为VGG19网络&#xff0c;中间为34层的普通网络&#xf…

python笔记--socket_TCP模拟浏览器实现

""" 1,导包 2,创建TCP套接字 3,建立连接 4,拼接客户端请求报文 5,发送请求报文 6,接收响应报文 7,过滤出html页面 8,保存为html文件 9,关闭套接字 """ # 1,导包 import socket # 2,创建TCP套接字 tcp_socketsocket.socket(socket.AF_INET,socket…

西门子PLC基础指令4:置位指令 S、复位指令 R

布尔指令 1、置位指令 S Setbit 是要进行置位操作的地址的首地址&#xff0c;N 是从该首地址开始连续置位的位数 。 LD I0.0 // 装载输入继电器I0.0的状态&#xff08;当I0.0为ON时&#xff0c;执行后续指令&#xff09; S Q0.0, 3 // 从Q0.0开始&#xff0c;连续置位3…

2.3 子组件样式冲突详解

Vue2组件样式冲突的成因与解决方案组件样式冲突的根本原因在Vue单页面应用中&#xff0c;所有组件的DOM结构最终都会合并到同一个index.html 页面中。若子组件未使用scoped属性&#xff0c;其样式会默认全局生效&#xff0c;导致不同组件中相同选择器&#xff08;如h1、.contai…

26-数据仓库与Apache Hive

1.数据仓库 是什么&#xff1f;解决什么&#xff1f;1.1 数据仓库Data Warehouse 数仓 / DW 是一个用于存储、分析、报告的数据系统.目的&#xff1a;构建面向分析的集成数据环境&#xff0c;分析结构为企业提供决策支持。数仓专注于分析数仓本身不“”生产“”数据&#xff0c…

前端開發技術教學(二)

書接上回&#xff1a;前端開發技術教學(一) -CSDN博客 必要資源&#xff1a;TRAE - The Real AI Engineer 目录 一) 自定義函數 - function 二) DOM操控 DOM事件 a.) onclick b.) onkeydown 三) AI寫代碼 書接上回說到的前端3種主語言以及其用法&#xff0c;這期我們…