pythonic生物人

多子图自由~

多子图是文献、日常数据展示常用方法,本文细讲子图(Axes)。

Image

节选自👉Python matplotlib教程(优惠中)

Python Matplotlib中创建Axes时,是基于matplotlib.figure.Figure或者matplotlib.pyplot上的方法。以下详细介绍不同的添加Axes方式,


6.2.1 add_axes逐个添加Axes

add_axes可以手动在一个Figure上创建自定义位置的Axes,通过left、bottom、width和height四个参数指定Axes的精确位置和大小,这四个参数都是Figure的width和height的百分比,

##6.1.4_01
# -*- encoding: utf-8 -*-
'''
未经过允许禁止转载!
@Author  :   公众号:pythonic生物人
@Desc    :   6.2.1 add_axes逐个添加Axes
'''

import matplotlib.pyplot as plt

# 创建一个matplotlib.figure.Figure
fig = plt.figure(dpi=150, edgecolor='grey')
fig.patch.set_linewidth(1)

# 在matplotlib.figure.Figure上添加四个Axes,并自定义它们的位置
ax1 = fig.add_axes([
    0.1,  # 左边距:Axes左边与Figure左边的距离,占Figure宽度的10%(0到1之间的比例)
    0.6,  # 底边距:Axes底边与Figure底边的距离,占Figure高度的60%(0到1之间的比例)
    0.35,  # 宽度:Axes的宽度,占Figure总宽度的35%(0到1之间的比例)
    0.3
])  # 高度:Axes的高度,占Figure总高度的30%(0到1之间的比例)

ax2 = fig.add_axes([0.6, 0.6, 0.35, 0.3])
ax3 = fig.add_axes([0.1, 0.1, 0.35, 0.3])
ax4 = fig.add_axes([0.6, 0.1, 0.35, 0.3])

# 给每个Axes添加标题
ax1.set_title("Axes 1")
ax2.set_title("Axes 2")
ax3.set_title("Axes 3")
ax4.set_title("Axes 4")

plt.show()

Image

6.2.2 Figure.add_subplot逐个添加Axes

在Figure上逐个添加Axes,使用从1开始的索引(类似Matlab)。可以通过指定网格单元的范围来跨越多列或多行。

##6.2.2_01
# -*- encoding: utf-8 -*-
'''
未经过允许禁止转载!
@Author  :   公众号:pythonic生物人
@Desc    :   6.2.2 Figure.add_subplot逐个添加Axes
'''

import matplotlib.pyplot as plt

# 创建一个matplotlib.figure.Figure
fig = plt.figure(dpi=150, edgecolor='grey')
fig.patch.set_linewidth(1)

# 使用add_subplot创建3个Axes
# 2行2列的网格
ax1 = fig.add_subplot(2, 2, 1)  # 第一个子图,占据第一行第一列
ax1.set_title("Axes 1")

ax2 = fig.add_subplot(2, 2, 2)  # 第二个子图,占据第一行第二列
ax2.set_title("Axes 2")

# 第三个子图,跨越多列(跨越第二行的两列)
ax3 = fig.add_subplot(2, 2, (3, 4))  # 使用(3, 4)来表示跨越第三、第四个网格单元
ax3.set_title("Axes 3 (spanning columns)")

# 调整子图间距
plt.tight_layout()

# 显示图形
plt.show()

Image

6.2.3 pyplot.subplot逐个添加Axes

功能同章节“6.2.2 Figure.add_subplot逐个添加Axes”,只是本节使用了pyplot中的subplot方法,

##6.2.3_01
# -*- encoding: utf-8 -*-
'''
未经过允许禁止转载!
@Author  :   公众号:pythonic生物人
@Desc    :   6.2.3 pyplot.subplot逐个添加Axes
'''

import matplotlib.pyplot as plt

# 创建一个matplotlib.figure.Figure
fig = plt.figure(dpi=150, edgecolor='grey')
fig.patch.set_linewidth(1)

# 使用pyplot.subplot创建3个Axes
# 2行2列的网格
ax1 = plt.subplot(2, 2, 1)  # 第一个子图,占据第一行第一列
ax1.set_title("Axes 1")

ax2 = plt.subplot(2, 2, 2)  # 第二个子图,占据第一行第二列
ax2.set_title("Axes 2")

# 第三个子图,跨越多列(跨越第二行的两列)
ax3 = plt.subplot(2, 2, (3, 4))  # 使用(3, 4)来表示跨越第三、第四个网格单元
ax3.set_title("Axes 3 (spanning columns)")

plt.tight_layout()  # 调整子图间距
plt.show()

Image

6.2.4 Figure.subplot_mosaic更灵活添加Axes

又一种创建图形和网格布局的简单方法,并且具有额外的灵活性,Axes(坐标轴)也可以跨越行或列。Axes 会以带标签的字典形式返回,而不是数组。

##6.2.4_01
# -*- encoding: utf-8 -*-
'''
未经过允许禁止转载!
@Author  :   公众号:pythonic生物人
@Desc    :   6.2.4 Figure.subplot_mosaic更灵活添加Axes
'''

import matplotlib.pyplot as plt

# 创建一个matplotlib.figure.Figure
fig = plt.figure(dpi=150, edgecolor='grey')
fig.patch.set_linewidth(1)

# 使用subplot_mosaic创建带有标签的布局
# 'A'、'B' 等为标签,可以通过字典访问
layout = """
    AAB
    CDD
    EEE
"""

# 创建子图布局,使用字符串表示法定义各个子图的位置
ax_dict = fig.subplot_mosaic(layout)

# 给每个子图添加标题
ax_dict['A'].set_title('Axes A (spanning 2 columns)')
ax_dict['B'].set_title('Axes B')
ax_dict['C'].set_title('Axes C')
ax_dict['D'].set_title('Axes D')
ax_dict['E'].set_title('Axes E (spanning 2 columns)')

# 调整子图间距
plt.tight_layout()

# 显示图形
plt.show()

Image

6.2.5 pyplot.subplot_mosaic更灵活添加Axes

同“ 6.2.4 Figure.subplot_mosaic更灵活添加Axes”,

##6.2.5_01
# -*- encoding: utf-8 -*-
'''
未经过允许禁止转载!
@Author  :   公众号:pythonic生物人
@Desc    :   6.2.5 pyplot.subplot_mosaic更灵活添加Axes
'''

import matplotlib.pyplot as plt

## 使用pyplot.subplot_mosaic创建带有标签的布局
# 'A'、'B' 等为标签,可以通过字典访问
layout = """
    AAB
    CDD
    EEE
"""

# 使用pyplot接口创建带有标签的子图布局
fig, ax_dict = plt.subplot_mosaic(layout, dpi=150)

# 给每个子图添加标题
ax_dict['A'].set_title('Axes A (spanning 2 columns)')
ax_dict['B'].set_title('Axes B')
ax_dict['C'].set_title('Axes C')
ax_dict['D'].set_title('Axes D')
ax_dict['E'].set_title('Axes E (spanning 2 columns)')

plt.tight_layout()

# 显示图形
plt.show()

Image

6.2.6 GridSpec添加Axes

GridSpec提供了更精细的Axes控制,可以轻松实现跨行跨列,通过指定网格的行和列,用户可以将Axes放在任意网格单元内,并可以灵活地调整各个单元的大小。

#6.2.6_01
# -*- encoding: utf-8 -*-
'''
未经过允许禁止转载!
@Author  :   公众号:pythonic生物人
@Desc    :   6.2.6 GridSpec添加Axes
'''

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

# 创建一个matplotlib.figure.Figure
fig = plt.figure(dpi=150)

# 创建GridSpec布局

gs = gridspec.GridSpec(
    3,
    3,  #3行3列的网格
    figure=fig)

# 创建第一个子图,跨越第一行的两列
ax1 = fig.add_subplot(gs[0, 0:2])  # 占据第一行的前两列
ax1.set_title("Axes 1 (spanning 2 columns)")

# 创建第二个子图,位于第一行第三列
ax2 = fig.add_subplot(gs[0, 2])  # 占据第一行的第三列
ax2.set_title("Axes 2")

# 创建第三个子图,跨越第二行和第三行的第一列
ax3 = fig.add_subplot(gs[1:, 0])  # 占据第二、第三行的第一列
ax3.set_title("Axes 3 (spanning 2 rows)")

# 创建第四个子图,位于第二行第二列
ax4 = fig.add_subplot(gs[1, 1])  # 占据第二行的第二列
ax4.set_title("Axes 4")

# 创建第五个子图,位于第二行第三列
ax5 = fig.add_subplot(gs[1, 2])  # 占据第二行的第三列
ax5.set_title("Axes 5")

# 创建第六个子图,跨越第三行的第二、第三列
ax6 = fig.add_subplot(gs[2, 1:3])  # 占据第三行的第二、第三列
ax6.set_title("Axes 6 (spanning 2 columns)")

# 调整子图间距
plt.tight_layout()

plt.show()

Image

6.2.7 Figure.subfigures添加嵌套Axes

有时候,需要在同一个Figure中放置两个或更多子图组,但子图组的功能和布局上是独立的,而且每个子图组中可以嵌套Axes。

#6.2.7_01
# -*- encoding: utf-8 -*-
'''
未经过允许禁止转载!
@Author  :   公众号:pythonic生物人
@Desc    :   6.2.7 Figure.subfigures添加嵌套Axes
'''

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(15, 8), dpi=150)

# 创建外层子图组(3列)
subfigs = fig.subfigures(1, 3, wspace=0.05, hspace=0.05)

# 左侧子图组(6个子图,2行3列)
left_subfig = subfigs[0].subplots(2, 3)  # 2行3列
for i, ax in enumerate(left_subfig.flatten(), start=1):
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_facecolor('lightgray')
    ax.set_title(f"Left Subplot {i}")

subfigs[0].set_facecolor('lightcoral')
subfigs[0].text(0.5, 0.95, "Left Subfigures", fontsize=16, ha='center')

# 中间子图组(4个子图,2行2列)
middle_subfig = subfigs[1].subplots(2, 2)  # 2行2列
for i, ax in enumerate(middle_subfig.flatten(), start=1):
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_facecolor('lightgray')
    ax.set_title(f"Middle Subplot {i}")
subfigs[1].set_facecolor('lightgreen')
subfigs[1].text(0.5, 0.95, "Middle Subfigures", fontsize=16, ha='center')

# 右侧子图组(3个子图,3行1列)
right_subfig = subfigs[2].subplots(3, 1)  # 3行1列
for i, ax in enumerate(right_subfig.flatten(), start=1):
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_facecolor('lightgray')
    ax.set_title(f"Right Subplot {i}")
subfigs[2].set_facecolor('lightblue')
subfigs[2].text(0.5, 0.95, "Right Subfigures", fontsize=16, ha='center')

plt.show()

Image

在同一个Figure中放置3个子图组,每个子图组中嵌套多个Axes。


6.2.8 多子图方法比较

add_axes、add_subplot、subplot_mosaic、GridSpec、subfigures在Matplotlib中添加子图时的优缺点、适用场景比较:

方法优点缺点适用场景
add_axes精确控制子图位置和大小,适合复杂布局使用不直观,布局调整繁琐需要自定义子图布局时
add_subplot简单直观,适合网格布局不够灵活,子图间可能有不规则空隙规则网格布局,快速生成子图
subplot_mosaic直观命名子图,适合复杂布局功能较新,灵活性不如 add_axes 或 GridSpec自定义网格子图布局,命名子图
GridSpec高度灵活,子图可以跨行列,适合不规则网格布局语法稍复杂,代码较多子图尺寸不均,布局复杂
subfigures支持独立子图组,每组有独立布局和样式设置复杂,需要较多代码创建多个不同类别的子图组,嵌套图表


-END-

节选自:👉保姆级matplotlib教程—详细目录

交流学习(备注399)

图片