pin_drop当前位置:知识文库 ❯ 图文

matplotlib子图subplot()函数详解 - Python多图布局绘制

概述

子图(subplot)允许在同一个Figure中绘制多个图表,便于对比和展示多组相关数据。matplotlib提供了plt.subplot()plt.subplots()GridSpec三种创建子图的方式。plt.subplots()是最常用的方式,支持灵活的网格布局;GridSpec支持更复杂的不规则布局。

在数据分析和机器学习项目中,我们经常需要同时展示多个维度的数据或不同模型的结果。子图功能使得我们可以在单张图片中呈现丰富的信息,大大提升图表的表现力和信息密度。


语法与参数说明

三种创建方式

代码示例

# 方式1:逐个创建
plt.subplot(nrows, ncols, index)

# 方式2:一次性创建(推荐)
fig, axes = plt.subplots(nrows, ncols)

# 方式3:GridSpec灵活布局
from matplotlib.gridspec import GridSpec
gs = GridSpec(nrows, ncols)
ax = fig.add_subplot(gs[row_slice, col_slice])

plt.subplots()核心参数

参数 类型 默认值 说明
nrows int 1 行数
ncols int 1 列数
sharex bool/str False 是否共享X轴
sharey bool/str False 是否共享Y轴
figsize tuple None 图形大小(宽, 高)
dpi int 100 分辨率
tight_layout bool False 是否自动调整间距

sharex/sharey选项

说明
False 各子图独立坐标轴
True 共享坐标轴,只显示底部/左侧刻度
'all' 同True
'row' 每行共享Y轴
'col' 每列共享X轴

返回值

plt.subplots()返回(Figure, Axes)元组,其中Axes的形态取决于子图数量:

  • 1x1:返回单个Axes对象

  • 1xN或Nx1:返回一维数组

  • NxM:返回二维数组


代码示例

示例1:规则网格子图

创建2x2的子图网格,分别绘制三角函数,使用sharex和sharey共享坐标轴。

代码示例

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2 * np.pi, 100)

fig, axes = plt.subplots(2, 2, figsize=(12, 8), sharex=True, sharey=True)

# 左上:正弦
axes[0, 0].plot(x, np.sin(x), 'b-')
axes[0, 0].set_title('sin(x)')
axes[0, 0].grid(True, alpha=0.3)

# 右上:余弦
axes[0, 1].plot(x, np.cos(x), 'r-')
axes[0, 1].set_title('cos(x)')
axes[0, 1].grid(True, alpha=0.3)

# 左下:正切
axes[1, 0].plot(x, np.tan(x), 'g-')
axes[1, 0].set_title('tan(x)')
axes[1, 0].set_ylim(-5, 5)
axes[1, 0].grid(True, alpha=0.3)

# 右下:组合
axes[1, 1].plot(x, np.sin(x), 'b-', label='sin')
axes[1, 1].plot(x, np.cos(x), 'r-', label='cos')
axes[1, 1].set_title('sin & cos')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)

fig.suptitle('Trigonometric Functions', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig('grid_subplot.png', dpi=100, bbox_inches='tight')
print("网格子图已保存")

输出:

代码示例

网格子图已保存

示例2:不同类型图表组合

在1x3的子图布局中,组合展示折线图、柱状图和直方图,适合数据分析报告。

代码示例

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(42)
data = np.random.normal(50, 15, 200)
categories = ['A', 'B', 'C', 'D']
values = [25, 35, 20, 20]

fig, axes = plt.subplots(1, 3, figsize=(15, 5))

# 折线图
axes[0].plot(np.cumsum(np.random.randn(50)), 'b-')
axes[0].set_title('Line Chart')
axes[0].grid(True, alpha=0.3)

# 柱状图
axes[1].bar(categories, values, color=['#2196F3', '#4CAF50', '#FF9800', '#9C27B0'])
axes[1].set_title('Bar Chart')

# 直方图
axes[2].hist(data, bins=20, color='#FF5722', edgecolor='white', alpha=0.8)
axes[2].set_title('Histogram')

fig.suptitle('Different Chart Types', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig('mixed_subplot.png', dpi=100, bbox_inches='tight')
print("混合子图已保存")

输出:

代码示例

混合子图已保存

示例3:GridSpec不规则布局

使用GridSpec创建复杂的不规则布局,主图占据大部分空间,右侧和底部放置小图。

代码示例

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.gridspec import GridSpec

np.random.seed(42)
x = np.linspace(0, 10, 100)

fig = plt.figure(figsize=(12, 8))
gs = GridSpec(3, 3, figure=fig, hspace=0.3, wspace=0.3)

# 大图:占2行2列
ax_main = fig.add_subplot(gs[0:2, 0:2])
ax_main.plot(x, np.sin(x), 'b-', linewidth=2)
ax_main.plot(x, np.cos(x), 'r--', linewidth=2)
ax_main.set_title('Main Plot')
ax_main.grid(True, alpha=0.3)

# 右上小图
ax_top = fig.add_subplot(gs[0, 2])
ax_top.hist(np.random.normal(0, 1, 200), bins=20, color='#4CAF50', edgecolor='white')
ax_top.set_title('Distribution')

# 右中小图
ax_mid = fig.add_subplot(gs[1, 2])
ax_mid.scatter(np.random.randn(30), np.random.randn(30), c='#FF5722', alpha=0.6)
ax_mid.set_title('Scatter')

# 底部宽图
ax_bottom = fig.add_subplot(gs[2, :])
ax_bottom.bar(range(10), np.random.randint(10, 100, 10), color='#2196F3')
ax_bottom.set_title('Bar Chart')

fig.suptitle('GridSpec Layout', fontsize=14, fontweight='bold')
plt.savefig('gridspec_layout.png', dpi=100, bbox_inches='tight')
print("GridSpec布局已保存")

输出:

代码示例

GridSpec布局已保存

实际应用场景

  • 数据分析报告:使用子图同时展示趋势、分布和对比,提升信息密度

  • 机器学习:使用子图展示不同超参数下的训练曲线或特征重要性

  • 仪表盘:使用GridSpec创建大小不一的图表区域,实现专业数据大屏


注意事项

注意:plt.subplots()返回的axes在1x1时为单个对象,1xN或Nx1时为一维数组,NxM时为二维数组

注意:使用tight_layout()自动调整子图间距,避免标签重叠;也可手动调用fig.subplots_adjust()微调

注意:sharex/sharey=True时只有边缘子图显示刻度标签,节省空间并保持整洁


子图创建方式对比

方式 灵活性 代码量 适用场景
plt.subplot() 简单顺序布局
plt.subplots() 规则网格布局(推荐)
GridSpec 不规则布局

小结

  • plt.subplots()是最常用的子图创建方式,返回Figure和Axes数组

  • sharex/sharey参数控制坐标轴共享,减少冗余刻度

  • GridSpec支持不规则布局,子图可跨越多行多列

  • tight_layout()自动调整间距,suptitle()添加总标题


练习题

练习1

使用plt.subplots()创建2x2子图,分别绘制sin、cos、tan和sin+cos曲线

练习2

创建1x3子图,分别绘制折线图、柱状图和散点图,共享Y轴

练习3

使用GridSpec创建一个主图占2/3面积,右侧两个小图的布局

常见问题

plt.subplot()和plt.subplots()有什么区别?

plt.subplot()逐个创建子图,需要指定索引位置,代码较冗长;plt.subplots()一次性创建所有子图,返回Figure和Axes对象数组,代码更简洁,推荐使用。

如何解决子图标签重叠的问题?

使用plt.tight_layout()自动调整子图间距,或使用fig.subplots_adjust(hspace=0.3, wspace=0.3)手动设置水平和垂直间距。如果使用suptitle()添加总标题,可配合tight_layout(rect=[0, 0, 1, 0.95])避免重叠。

GridSpec如何实现子图跨越多行多列?

使用切片语法,如gs[0:2, 0:2]表示占据第0-1行和第0-1列(2x2区域),gs[2, :]表示占据第2行的所有列。通过灵活组合切片,可以实现各种不规则布局。

sharex=True后如何为特定子图显示X轴刻度?

默认情况下sharex=True只有底部子图显示X轴刻度。如果需要特定子图显示,可以使用ax.tick_params(labelbottom=True)强制显示,或者使用sharex='col'实现按列共享。

fig.suptitle()和ax.set_title()有什么区别?

fig.suptitle()为整个Figure添加总标题,位于所有子图之上;ax.set_title()为单个子图添加标题。通常在多子图布局中,同时使用suptitle作为总标题和各子图的set_title作为局部标题。

标签: matplotlib 子图 GridSpec 多图布局 Python教程 数据可视化

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: matplotlib直方图hist()函数详解 - Python数据分布可视化 下一篇: matplotlib图例legend()函数详解 - Python图表图例设置教程

poll相关推荐