首页 > Python资料 博客日记

Python Matplotlib 多图显示 subplot:从组合布局到嵌套图形的全面解析

2025-01-02 07:00:06Python资料围观27

Python资料网推荐Python Matplotlib 多图显示 subplot:从组合布局到嵌套图形的全面解析这篇文章给大家,欢迎收藏Python资料网享受知识的乐趣

Python Matplotlib 多图显示 subplot:从组合布局到嵌套图形的全面解析

本篇文章详解了 Matplotlib 的多图合并显示的多种方法,包括基础的子图组合、栅格布局、多图嵌套以及孪生坐标系的应用。通过详尽的代码示例与运行结果,读者可以快速掌握如何在一个窗口中展示多个图形。文章涵盖了均匀子图排列、跨行跨列布局的创建技巧,以及如何通过 subplot2gridGridSpec 实现更加精细的栅格图布局。此外,文章还介绍了如何嵌套多个图形,实现主图与子图的组合效果,并通过孪生坐标系为同一图形添加多个 Y 轴以展示不同维度的数据。丰富的注释与图例为每种方法提供了直观的解析,是学习 Matplotlib 多图显示的实用指南。不论是数据科学初学者,还是需要制作复杂图表的开发者,都能从中获益匪浅。

一 子图组合 subplot

1 均匀图
def subplot01():
    # 创建一个图形窗口
    plt.figure()
    # 在2x2的网格中创建第1个子图位置
    plt.subplot(2, 2, 1)
    # 在第1个子图中绘制一条线,从(0,0)到(1,1)
    plt.plot([0, 1], [0, 1])

    # 在2x2的网格中创建第2个子图位置
    plt.subplot(2, 2, 2)
    # 在第2个子图中绘制一条线,从(0,0)到(1,2)
    plt.plot([0, 1], [0, 2])

    # 在2x2的网格中创建第3个子图位置,使用另一种指定方式223
    plt.subplot(223)
    # 在第3个子图中绘制一条线,从(0,0)到(1,3)
    plt.plot([0, 1], [0, 3])

    # 在2x2的网格中创建第4个子图位置,使用另一种指定方式224
    plt.subplot(224)
    # 在第4个子图中绘制一条线,从(0,0)到(1,4)
    plt.plot([0, 1], [0, 4])

    # 显示图形窗口
    plt.show()
运行结果

2 跨列图
def subplot02():
    # 在2行1列的网格中创建第1个子图位置,此子图占据第一行的全部
    plt.subplot(2, 1, 1)
    # 在第1个子图中绘制一条线,从(0,0)到(1,1)
    plt.plot([0, 1], [0, 1])

    # 在2行3列的网格中创建第4个子图位置,这里的子图位于第二行的第一个位置
    plt.subplot(2, 3, 4)
    # 在第2个子图中绘制一条线,从(0,0)到(1,2)
    plt.plot([0, 1], [0, 2])

    # 使用简写方式235,等同于在2行3列的网格中指定第5个子图,即第二行的第二个位置
    plt.subplot(235)
    # 在第3个子图中绘制一条线,从(0,0)到(1,3)
    plt.plot([0, 1], [0, 3])

    # 使用简写方式236,等同于在2行3列的网格中指定第6个子图,即第二行的第三个位置
    plt.subplot(236)
    # 在第4个子图中绘制一条线,从(0,0)到(1,4)
    plt.plot([0, 1], [0, 4])

    # 显示图形窗口
    plt.show()
运行结果

二 栅格布局 grid

1 使用 subplot2grid 创建子图布局
def subplot_grid_01():
    # 创建一个新的图形窗口
    plt.figure()
    # 创建一个子图,占据3行3列网格的第0行所有3列
    ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
    ax1.plot([1, 2], [1, 2])  # 在ax1中绘制线图
    ax1.set_title('ax1_title')  # 设置ax1的标题

    # 创建一个子图,占据第1行的前2列
    ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
    # 创建一个子图,从第1行第3列开始,纵向跨越2行
    ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
    # 创建一个子图,在第2行第1列
    ax4 = plt.subplot2grid((3, 3), (2, 0))
    # 创建一个子图,在第2行第2列
    ax5 = plt.subplot2grid((3, 3), (2, 1))

    # 在ax4中绘制散点图
    ax4.scatter([1, 2], [2, 2])
    # 设置ax4的x轴标签
    ax4.set_xlabel('ax4_x')
    # 设置ax4的y轴标签
    ax4.set_ylabel('ax4_y')

    # 显示图形窗口
    plt.show()
运行结果

2 通过 GridSpec 创建子图布局
def subplot_grid_spec():
    # 创建一个图形窗口
    plt.figure()
    # 初始化一个网格布局,3行3列
    gs = gridspec.GridSpec(3, 3)

    # 创建一个子图,占据第一行的所有3列
    plt.subplot(gs[0, :])
    # 创建一个子图,占据第二行的前两列
    plt.subplot(gs[1, :2])
    # 创建一个子图,占据第二行的第三列,并延伸至第三行
    plt.subplot(gs[1:, 2])
    # 创建一个子图,位于最后一行的第一列
    plt.subplot(gs[-1, 0])
    # 创建一个子图,位于最后一行的第二列
    plt.subplot(gs[-1, -2])

    # 显示图形
    plt.show()
运行结果

3 使用 plt.subplots 创建子图网格
def subplot_s():
    # 创建一个2行2列的子图网格,并共享x轴和y轴
    # 返回的f是整个图形对象,((ax11, ax12), (ax13, ax14))是子图的坐标轴对象
    f, ((ax11, ax12), (ax13, ax14)) = plt.subplots(2, 2, sharex=True, sharey=True)

    # 在第一个子图(ax11)中绘制散点图
    ax11.scatter([1, 2], [1, 2])

    # 调整子图之间的间距,以防止重叠
    plt.tight_layout()

    # 显示图形
    plt.show()
代码释义
  • plt.subplots(2, 2, sharex=True, sharey=True)

  • 2, 2:指定子图网格为2行2列,总共有4个子图。

  • sharex=Truesharey=True:表示子图之间共享x轴和y轴的刻度,这样可以确保所有子图的刻度范围一致。

  • 返回值:

    • f 是整个图形对象,可以用来设置整体图形的属性。
    • ((ax11, ax12), (ax13, ax14)) 是一个包含4个子图坐标轴的二维元组,分别对应每个子图。
  • ax11.scatter([1, 2], [1, 2])

  • 在第一个子图 ax11 中绘制散点图,点的坐标为 (1, 1)(2, 2)

  • plt.tight_layout()

  • 自动调整子图之间的间距,以避免子图之间出现重叠,保证整体布局更美观。

该函数绘制了一个包含4个子图的网格,每个子图共享相同的x轴和y轴刻度。只有第一个子图 ax11 中绘制了散点图,其余子图没有内容。如果需要在其他子图中添加内容,可以调用 ax12, ax13, ax14 来绘制。

运行结果

三 多图嵌套 plot_in_plot

def plot_in_plot():
    # 初始化figure对象
    fig = plt.figure()

    # 创建基础数据
    x = [1, 2, 3, 4, 5, 6, 7]
    y = [1, 3, 4, 2, 5, 8, 6]

    # 设置大图的坐标轴位置
    left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
    ax1 = fig.add_axes([left, bottom, width, height])  # 添加大图
    ax1.plot(x, y, 'r')  # 大图中绘制红色线条
    ax1.set_xlabel('x')  # 设置x轴标签
    ax1.set_ylabel('y')  # 设置y轴标签
    ax1.set_title('title')  # 设置大图标题

    # 在大图中嵌入小图1:左上角
    left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
    ax2 = fig.add_axes([left, bottom, width, height])  # 添加小图1
    ax2.plot(y, x, 'b')  # 小图1中绘制蓝色线条
    ax2.set_xlabel('x')  # 设置小图1的x轴标签
    ax2.set_ylabel('y')  # 设置小图1的y轴标签
    ax2.set_title('title inside 1')  # 设置小图1标题

    # 在大图中嵌入小图2:右下角
    plt.axes([0.6, 0.2, 0.25, 0.25])  # 添加小图2
    plt.plot(y[::-1], x, 'g')  # 小图2中绘制绿色线条,y数据逆序处理
    plt.xlabel('x')  # 设置小图2的x轴标签
    plt.ylabel('y')  # 设置小图2的y轴标签
    plt.title('title inside 2')  # 设置小图2标题

    # 显示最终图形
    plt.show()
运行结果

四 孪生坐标系 twinx

def twinx():
    # 创建x轴的数据,从0到10,步长0.1
    x = np.arange(0, 10, 0.1)
    # 创建y1数据,y1是x的平方乘以0.05
    y1 = 0.05 * x ** 2
    # 创建y2数据,y2是y1的相反数
    y2 = -1 * y1

    # 创建一个图和一个子图轴ax1
    _, ax1 = plt.subplots()
    # 创建第二个y轴ax2,共享ax1的x轴
    ax2 = ax1.twinx()

    # 在ax1上绘制x和y1的关系,线条为绿色实线
    ax1.plot(x, y1, 'g-')  # green, solid line
    # 设置ax1的x轴和y轴标签
    ax1.set_xlabel('X data')
    ax1.set_ylabel('Y1 data', color='g')

    # 在ax2上绘制x和y2的关系,线条为蓝色实线
    ax2.plot(x, y2, 'b-')  # blue
    # 设置ax2的y轴标签,并设置文字颜色为蓝色
    ax2.set_ylabel('Y2 data', color='b')

    # 显示图表
    plt.show()

运行结果

五 完整代码示例

# This is a sample Python script.

# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np


def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press ⌘F8 to toggle the breakpoint.


def subplot01():
    # 创建一个图形窗口
    plt.figure()
    # 在2x2的网格中创建第1个子图位置
    plt.subplot(2, 2, 1)
    # 在第1个子图中绘制一条线,从(0,0)到(1,1)
    plt.plot([0, 1], [0, 1])

    # 在2x2的网格中创建第2个子图位置
    plt.subplot(2, 2, 2)
    # 在第2个子图中绘制一条线,从(0,0)到(1,2)
    plt.plot([0, 1], [0, 2])

    # 在2x2的网格中创建第3个子图位置,使用另一种指定方式223
    plt.subplot(223)
    # 在第3个子图中绘制一条线,从(0,0)到(1,3)
    plt.plot([0, 1], [0, 3])

    # 在2x2的网格中创建第4个子图位置,使用另一种指定方式224
    plt.subplot(224)
    # 在第4个子图中绘制一条线,从(0,0)到(1,4)
    plt.plot([0, 1], [0, 4])

    # 显示图形窗口
    plt.show()


def subplot02():
    # 在2行1列的网格中创建第1个子图位置,此子图占据第一行的全部
    plt.subplot(2, 1, 1)
    # 在第1个子图中绘制一条线,从(0,0)到(1,1)
    plt.plot([0, 1], [0, 1])

    # 在2行3列的网格中创建第4个子图位置,这里的子图位于第二行的第一个位置
    plt.subplot(2, 3, 4)
    # 在第2个子图中绘制一条线,从(0,0)到(1,2)
    plt.plot([0, 1], [0, 2])

    # 使用简写方式235,等同于在2行3列的网格中指定第5个子图,即第二行的第二个位置
    plt.subplot(235)
    # 在第3个子图中绘制一条线,从(0,0)到(1,3)
    plt.plot([0, 1], [0, 3])

    # 使用简写方式236,等同于在2行3列的网格中指定第6个子图,即第二行的第三个位置
    plt.subplot(236)
    # 在第4个子图中绘制一条线,从(0,0)到(1,4)
    plt.plot([0, 1], [0, 4])

    # 显示图形窗口
    plt.show()


def subplot_grid_01():
    # 创建一个新的图形窗口
    plt.figure()
    # 创建一个子图,占据3行3列网格的第0行所有3列
    ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
    ax1.plot([1, 2], [1, 2])  # 在ax1中绘制线图
    ax1.set_title('ax1_title')  # 设置ax1的标题

    # 创建一个子图,占据第1行的前2列
    ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
    # 创建一个子图,从第1行第3列开始,纵向跨越2行
    ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
    # 创建一个子图,在第2行第1列
    ax4 = plt.subplot2grid((3, 3), (2, 0))
    # 创建一个子图,在第2行第2列
    ax5 = plt.subplot2grid((3, 3), (2, 1))

    # 在ax4中绘制散点图
    ax4.scatter([1, 2], [2, 2])
    # 设置ax4的x轴标签
    ax4.set_xlabel('ax4_x')
    # 设置ax4的y轴标签
    ax4.set_ylabel('ax4_y')

    # 显示图形窗口
    plt.show()


def subplot_grid_spec():
    # 创建一个图形窗口
    plt.figure()
    # 初始化一个网格布局,3行3列
    gs = gridspec.GridSpec(3, 3)

    # 创建一个子图,占据第一行的所有3列
    plt.subplot(gs[0, :])
    # 创建一个子图,占据第二行的前两列
    plt.subplot(gs[1, :2])
    # 创建一个子图,占据第二行的第三列,并延伸至第三行
    plt.subplot(gs[1:, 2])
    # 创建一个子图,位于最后一行的第一列
    plt.subplot(gs[-1, 0])
    # 创建一个子图,位于最后一行的第二列
    plt.subplot(gs[-1, -2])

    # 显示图形
    plt.show()


def subplot_s():
    # 创建一个2行2列的子图网格,并共享x轴和y轴
    # 返回的f是整个图形对象,((ax11, ax12), (ax13, ax14))是子图的坐标轴对象
    f, ((ax11, ax12), (ax13, ax14)) = plt.subplots(2, 2, sharex=True, sharey=True)

    # 在第一个子图(ax11)中绘制散点图
    ax11.scatter([1, 2], [1, 2])

    # 调整子图之间的间距,以防止重叠
    plt.tight_layout()

    # 显示图形
    plt.show()


def plot_in_plot():
    # 初始化figure对象
    fig = plt.figure()

    # 创建基础数据
    x = [1, 2, 3, 4, 5, 6, 7]
    y = [1, 3, 4, 2, 5, 8, 6]

    # 设置大图的坐标轴位置
    left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
    ax1 = fig.add_axes([left, bottom, width, height])  # 添加大图
    ax1.plot(x, y, 'r')  # 大图中绘制红色线条
    ax1.set_xlabel('x')  # 设置x轴标签
    ax1.set_ylabel('y')  # 设置y轴标签
    ax1.set_title('title')  # 设置大图标题

    # 在大图中嵌入小图1:左上角
    left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
    ax2 = fig.add_axes([left, bottom, width, height])  # 添加小图1
    ax2.plot(y, x, 'b')  # 小图1中绘制蓝色线条
    ax2.set_xlabel('x')  # 设置小图1的x轴标签
    ax2.set_ylabel('y')  # 设置小图1的y轴标签
    ax2.set_title('title inside 1')  # 设置小图1标题

    # 在大图中嵌入小图2:右下角
    plt.axes([0.6, 0.2, 0.25, 0.25])  # 添加小图2
    plt.plot(y[::-1], x, 'g')  # 小图2中绘制绿色线条,y数据逆序处理
    plt.xlabel('x')  # 设置小图2的x轴标签
    plt.ylabel('y')  # 设置小图2的y轴标签
    plt.title('title inside 2')  # 设置小图2标题

    # 显示最终图形
    plt.show()


def twinx():
    # 创建x轴的数据,从0到10,步长0.1
    x = np.arange(0, 10, 0.1)
    # 创建y1数据,y1是x的平方乘以0.05
    y1 = 0.05 * x ** 2
    # 创建y2数据,y2是y1的相反数
    y2 = -1 * y1

    # 创建一个图和一个子图轴ax1
    _, ax1 = plt.subplots()
    # 创建第二个y轴ax2,共享ax1的x轴
    ax2 = ax1.twinx()

    # 在ax1上绘制x和y1的关系,线条为绿色实线
    ax1.plot(x, y1, 'g-')  # green, solid line
    # 设置ax1的x轴和y轴标签
    ax1.set_xlabel('X data')
    ax1.set_ylabel('Y1 data', color='g')

    # 在ax2上绘制x和y2的关系,线条为蓝色实线
    ax2.plot(x, y2, 'b-')  # blue
    # 设置ax2的y轴标签,并设置文字颜色为蓝色
    ax2.set_ylabel('Y2 data', color='b')

    # 显示图表
    plt.show()


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('多图合并显示')
    # Subplot 多合一显示,均匀图中图
    subplot01()
    # Subplot 多合一显示,不均匀图中图
    subplot02()

    # Subplot 分格显示
    subplot_grid_01()
    subplot_grid_spec()
    subplot_s()

    # 图中图 plot in plot
    plot_in_plot()

    # 次坐标轴 twinx
    twinx()

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。

Hi, 多图合并显示

六 源码地址

代码地址:

国内看 Giteematplotlib/多图合并显示.py

国外看 GitHubmatplotlib/多图合并显示.py

七 参考

[1] Matplotlib 官网

[2] 莫烦 python


版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐