【技术专题】Matplotlib3 Python 数据可视化 - Matplotlib3 多子图及布局实现

大家好,我是锋哥。最近连载更新《Matplotlib3 Python 数据可视化》技术专题。

本课程讲解利用python进行数据可视化 科研绘图-Matplotlib,学习Matplotlib图形参数基本设置,绘图参数及主要函数,以及Matplotlib基础绘图,和Matplotlib高级绘图。同时也配套视频教程 《2026版 Matplotlib3 Python 数据可视化 视频教程》

Matplotlib 提供了多种创建多子图布局的方式,适用于数据对比、多维度可视化等场景。以下是三种核心方法及示例:

方法一:plt.subplots()(推荐)

适用场景:创建均匀网格布局的子图

plt.subplots() 是 Matplotlib 中用于批量创建图形(Figure)和子图(Axes) 的核心函数。它简化了多子图的布局管理,比传统的 plt.subplot() 更灵活高效。下面从功能、参数到示例详细解析:

ini 复制代码
fig, axes = plt.subplots(
    nrows=1,           # 子图行数 (默认1)
    ncols=1,           # 子图列数 (默认1)
    sharex=False,      # 是否共享x轴
    sharey=False,      # 是否共享y轴
    figsize=None,      # 图形大小 (元组: (宽, 高))
    constrained_layout=False,  # 自动调整布局
    **kwargs           # 其他Figure参数 (如dpi, facecolor等)
)

我们看一个示例:

ini 复制代码
import matplotlib.pyplot as plt
import numpy as np
​
# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
​
# 生成数据
x = np.linspace(0, 2 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = np.exp(x / 8)
​
# 创建2×2子图布局 (返回Figure对象和Axes数组)
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))
fig.suptitle('2×2 子图示例', fontsize=16)
​
# 绘制第一个子图
axs[0, 0].plot(x, y1, 'r-')
axs[0, 0].set_title('正弦函数')
axs[0, 0].grid(True)
​
# 绘制第二个子图
axs[0, 1].plot(x, y2, 'b--')
axs[0, 1].set_title('余弦函数')
axs[0, 1].set_facecolor('#f0f0f0')  # 设置背景色
​
# 绘制第三个子图 (对数坐标)
axs[1, 0].semilogy(x, y4, 'g-')
axs[1, 0].set_title('指数函数(对数Y轴)')
axs[1, 0].set_xlabel('X轴')
​
# 绘制第四个子图 (设置Y轴范围)
axs[1, 1].plot(x, y3, 'm-.')
axs[1, 1].set_title('正切函数')
axs[1, 1].set_ylim(-5, 5)  # 限制Y轴范围
​
# 调整布局
plt.tight_layout(rect=[0, 0, 1, 0.96])  # 为总标题留空间
plt.show()

运行截图:

方法二:GridSpec(复杂布局)

适用场景:创建不规则大小的子图

GridSpec 是 Matplotlib 中用于创建复杂、非均匀子图布局 的高级工具。它提供了比 plt.subplots() 更精细的控制,允许你定义不同大小的子图、跨行列的子图以及复杂的布局比例。

核心概念

GridSpec 通过定义一个网格系统来工作:

  • 将整个图形区域划分为行和列的网格
  • 允许子图跨越多个网格单元
  • 支持设置行和列的相对大小比例

基本语法:

ini 复制代码
from matplotlib.gridspec import GridSpec
​
# 创建 GridSpec 对象
gs = GridSpec(
    nrows,              # 网格总行数
    ncols,              # 网格总列数
    figure=None,        # 关联的 Figure 对象
    left=None,          # 网格左侧位置 (0-1)
    right=None,         # 网格右侧位置 (0-1)
    bottom=None,        # 网格底部位置 (0-1)
    top=None,           # 网格顶部位置 (0-1)
    wspace=None,        # 列间距 (宽度比例)
    hspace=None,        # 行间距 (高度比例)
    width_ratios=None,  # 列宽度比例列表
    height_ratios=None, # 行高度比例列表
)

我们看一个示例:

ini 复制代码
import matplotlib.pyplot as plt
import numpy as np
​
from matplotlib.gridspec import GridSpec
​
# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
​
# 生成数据
x = np.linspace(0, 2 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = np.exp(x / 8)
​
fig = plt.figure(figsize=(12, 8))
gs = GridSpec(3, 3, figure=fig)  # 3×3网格
​
# 创建跨行列的子图
ax1 = fig.add_subplot(gs[0, :])  # 首行全宽
ax2 = fig.add_subplot(gs[1, :-1])  # 第二行左侧两列
ax3 = fig.add_subplot(gs[1:, 2])  # 后两行最右列
ax4 = fig.add_subplot(gs[2, 0])  # 第三行首列
ax5 = fig.add_subplot(gs[2, 1])  # 第三行第二列
​
# 填充子图内容
ax1.plot(x, y1, color='tab:blue')
ax1.set_title('全宽标题区')
​
ax2.scatter(x, y2, c=y4, cmap='viridis')
ax2.set_title('散点图(带颜色映射)')
​
ax3.barh(x[:10], y4[:10], height=0.3)
ax3.set_title('横向柱状图')
​
ax4.pie([15, 30, 45, 10], labels=['A', 'B', 'C', 'D'])
ax4.set_title('饼图')
​
ax5.hist(np.random.randn(1000), bins=30)
ax5.set_title('直方图')
​
plt.suptitle('GridSpec 不规则布局', fontsize=16)
plt.tight_layout()
plt.show()

运行截图:

方法三:subplot2grid(传统方法)

适用场景:快速实现简单不规则布局

subplot2grid() 是 Matplotlib 中用于创建复杂子图布局 的灵活方法,特别适合构建非均匀网格布局。它结合了 subplot() 的简单性和 GridSpec 的灵活性,是创建自定义布局的高效工具。

核心概念

subplot2grid() 允许你:

  1. 定义一个网格系统(行和列)
  2. 指定子图的起始位置(行索引和列索引)
  3. 设置子图跨越的行数和列数
  4. 直接创建 Axes 对象

基本语法:

ini 复制代码
ax = plt.subplot2grid(
    shape,          # 网格形状 (行数, 列数)
    loc,            # 子图起始位置 (行索引, 列索引)
    rowspan=1,      # 子图跨越的行数(默认为1)
    colspan=1,      # 子图跨越的列数(默认为1)
    fig=None,       # 关联的Figure对象
    **kwargs        # 其他Axes参数
)

我们看一个示例:

ini 复制代码
import matplotlib.pyplot as plt
import numpy as np
​
# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
​
# 生成数据
x = np.linspace(0, 2 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = np.exp(x / 8)
​
plt.figure(figsize=(10, 6))
​
# 定义网格形状 (3×3)
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=2)
ax2 = plt.subplot2grid((3, 3), (0, 2), rowspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 0))
ax4 = plt.subplot2grid((3, 3), (1, 1))
ax5 = plt.subplot2grid((3, 3), (2, 0), colspan=3)
​
# 填充内容
ax1.fill_between(x, y1, y2, alpha=0.3)
ax2.plot(x, y3, 'r--', linewidth=2)
ax3.scatter(x[::5], y4[::5], s=50)
ax4.boxplot([np.random.normal(0, std, 100) for std in range(1, 4)])
ax5.stackplot(x, y1, y2, labels=['sin', 'cos'])
​
# 添加图例和标题
ax5.legend(loc='lower right')
plt.suptitle('subplot2grid 布局示例', fontsize=14)
plt.tight_layout()
plt.show()
相关推荐
西洼工作室2 小时前
python邮箱令牌/点击验证、邮箱验证码实现
前端·python
倔强的猴子(翻版)2 小时前
我用 Python 写了个排序库,一亿数据量下比 C 级 np.sort() 快 7 倍
人工智能·python·算法·阿里云·文心一言
郝学胜-神的一滴2 小时前
深入理解回归损失函数:MSE、L1 与 Smooth L1 的设计哲学
人工智能·python·程序人生·算法·机器学习·数据挖掘·回归
ZC跨境爬虫2 小时前
Python Django开发者转向微信小程序:从架构理解到第一行代码的完整准备指南
开发语言·python·ui·微信小程序·django
绘梨衣5472 小时前
django-elasticsearch-dsl-drf 搜索服务搭建教学文档
python·elasticsearch·django
测试员周周2 小时前
【AI测试系统】第6篇:需求扔进去,3 分钟出测试用例?AI测试系统的 RAG 知识增强实战
人工智能·python·功能测试·测试工具·测试用例
AI玫瑰助手2 小时前
Python入门:Windows/macOS/Linux系统安装Python教程
windows·python·macos
m0_738120722 小时前
网路安全编程——熟悉并使用Scapy简单实现捕捉主流邮箱协议(SMTP、POP3和IMAP) 的身份凭证
网络·python·网络协议·tcp/ip·安全·网络安全
new【一个】对象2 小时前
RAG详解
python·llm·agent·rag