Matplotlib 第三章 布局格式定方圆

一、子图

1.plt.subplots() 绘制均匀状态下的子图

(1)核心参数

参数 作用
nrows, ncols 子图的行数、列数(第一个数为行,第二个为列)
figsize 整个画布的大小,格式为 (宽, 高),单位英寸
sharex/sharey 是否共享横 / 纵轴刻度,True 表示所有子图共用一套刻度
tight_layout() 自动调整子图间距,避免标题、坐标轴标签重叠

(2)示例代码

复制代码
# 1. 创建2行5列的画布,指定大小,共享xy轴
fig, axs = plt.subplots(2, 5, figsize=(10, 4), sharex=True, sharey=True)
# 2. 给整个画布加总标题,字号20
fig.suptitle('样例1', size=20)
# 3. 双层循环遍历每个子图(i行j列)
for i in range(2):
    for j in range(5):
        # 4. 在当前子图绘制散点图,用随机数生成数据
        axs[i][j].scatter(np.random.randn(10), np.random.randn(10))
        # 5. 给每个子图加标题,标注行号列号
        axs[i][j].set_title('第%d行,第%d列'%(i+1,j+1))
        # 6. 统一设置xy轴范围,保证所有子图刻度一致
        axs[i][j].set_xlim(-5,5)
        axs[i][j].set_ylim(-5,5)
        # 7. 仅给最后一行加x轴标签,仅给第一列加y轴标签,避免重复
        if i==1: axs[i][j].set_xlabel('横坐标')
        if j==0: axs[i][j].set_ylabel('纵坐标')
# 8. 自动调整子图布局,防止文字重叠
fig.tight_layout()

效果:生成 2 行 ×5 列 共 10 个完全均匀的散点子图,所有子图共享 xy 轴,仅最后一行显示 x 轴标签、第一列显示 y 轴标签,布局整齐,无文字重叠。

2.极坐标子图 projection='polar'

除了常规直角坐标系,Matplotlib 支持通过 projection='polar' 创建极坐标图表:

示例代码

复制代码
import numpy as np
import matplotlib.pyplot as plt

N = 150
# 生成半径r(0~2)
r = 2 * np.random.rand(N)
# 生成角度theta(0~2π)
theta = 2 * np.pi * np.random.rand(N)
# 点的面积与半径平方成正比,越远的点越大
area = 200 * r**2
# 用角度作为颜色映射的依据
colors = theta

# 创建极坐标子图
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(8, 8))
# 绘制极坐标散点图,用hsv色盘,设置透明度0.75
scatter = plt.scatter(theta, r,c=colors,s=area,cmap='hsv',alpha=0.75)
plt.show()

效果:生成极坐标散点图,点的大小随半径增大而变大,颜色随角度变化,常用于方向、角度相关的数据可视化。

3.使用GridSpec 绘制非均匀子图

(1)作用

GridSpec 可以实现非均匀子图布局,包含两种场景:

  • 子图大小不同,但不跨行 / 跨列
  • 子图跨行 / 跨列,实现合并效果
  • 核心参数:width_ratios(列宽比例)、height_ratios(行高比例),通过切片 spec[i,j] 实现子图合并

(2)示例

(a)非均匀大小(不跨行 / 列)
复制代码
# 1. 创建画布
fig = plt.figure(figsize=(10, 4))
# 2. 创建2行5列的网格,指定列宽比例[1,2,3,4,5],行高比例[1,3]
spec = fig.add_gridspec(nrows=2, ncols=5, width_ratios=[1,2,3,4,5], height_ratios=[1,3])
fig.suptitle('样例2', size=20)

for i in range(2):
    for j in range(5):
        # 3. 按网格位置添加子图
        ax = fig.add_subplot(spec[i, j])
        ax.scatter(np.random.randn(10), np.random.randn(10))
        ax.set_title('第%d行,第%d列'%(i+1,j+1))
        # 4. 仅最后一行加x轴标签,第一列加y轴标签
        if i==1: ax.set_xlabel('横坐标')
        if j==0: ax.set_ylabel('纵坐标')
fig.tight_layout()

效果:生成 2 行 5 列子图,列宽从左到右按 1:2:3:4:5 递增,行高按 1:3(第二行更高),子图大小完全自定义,不改变行列结构。

(b)跨行 / 跨列合并子图
复制代码
# 1. 创建2行6列的网格,自定义列宽、行高比例
fig = plt.figure(figsize=(10, 4))
spec = fig.add_gridspec(nrows=2, ncols=6, width_ratios=[2,2.5,3,1,1.5,2], height_ratios=[1,2])
fig.suptitle('样例3', size=20)

# sub1:第0行,前3列(:3),合并成一个宽子图
ax = fig.add_subplot(spec[0, :3])
ax.scatter(np.random.randn(10), np.random.randn(10))

# sub2:第0行,第3-4列(3:5),合并成一个中等宽度子图
ax = fig.add_subplot(spec[0, 3:5])
ax.scatter(np.random.randn(10), np.random.randn(10))

# sub3:第5列,所有行(:,5),合并成一个高子图
ax = fig.add_subplot(spec[:, 5])
ax.scatter(np.random.randn(10), np.random.randn(10))

# sub4:第1行,第0列,单独子图
ax = fig.add_subplot(spec[1, 0])
ax.scatter(np.random.randn(10), np.random.randn(10))

# sub5:第1行,第1-4列(1:5),合并成一个大宽子图
ax = fig.add_subplot(spec[1, 1:5])
ax.scatter(np.random.randn(10), np.random.randn(10))

fig.tight_layout()

效果:通过切片语法 spec[行范围, 列范围] 实现子图合并,比如 spec[0, :3] 表示第 0 行、前 3 列合并,最终生成完全自定义的非均匀布局,满足复杂可视化需求。

  1. tight_layout() 必加:只要有多个子图,一定要调用这个方法,避免标题、标签重叠。
  2. 共享轴刻度 :当子图数据范围一致时,用 sharex=True/sharey=True 统一刻度,提升可读性。
  3. 切片语法GridSpec 的切片和 Python 列表切片完全一致,start:end 左闭右开,: 表示全部。
  4. 比例设置width_ratios/height_ratios 是相对比例,不是绝对像素,画布缩放时比例保持不变。
特性 plt.subplots() GridSpec
布局灵活性 仅支持均匀网格 支持非均匀大小、跨行 / 跨列,完全自定义
适用场景 简单、规则的子图布局 复杂、非规则的子图布局
代码复杂度 简单,适合新手 稍复杂,适合进阶需求
核心优势 快速生成,代码简洁 布局高度灵活,适配复杂可视化

二.子图上的方法

1.Axes 与 plt 的关系

  • plt(pyplot):类似 MATLAB 的接口,操作全局画布,适合快速出图。
  • ax(Axes 对象) :具体的子图对象,推荐在 Jupyter/DSW 中优先使用 ax,能精准控制单个子图,避免全局混乱。
  • 通用逻辑 :ax 上的方法和 plt 完全同名,只是调用方式从 plt.xxx() 变成了 ax.xxx()

2.基础绘图方法(ax 上的各类图表)

方法 作用 代码示例 关键参数说明
plot 绘制折线 / 曲线 ax.plot([1,2], [2,1]) 传入 x、y 数据列表
hist 绘制直方图 ax.hist(np.random.randn(1000)) 输入数据数组,自动分箱统计
scatter 散点图 见前文 x, y 坐标,点的大小 (s)、颜色 (c)
bar/barh 柱状图 / 水平柱状图 ax.bar(x, height) x 轴位置,柱高,宽度
pie 饼图 ax.pie(values) 数值列表,标签 labels

3.辅助线与网格(精修图表)

(1)绘制辅助线

方法 类型 代码示例 含义
axhline 水平辅助线 ax.axhline(y=0.5, xmin=0.2, xmax=0.8) 在 y=0.5 处画一条水平线,范围 xmin 到 xmax
axvline 垂直辅助线 ax.axvline(x=0.5, ymin=0.2, ymax=0.8) 在 x=0.5 处画一条垂直线
axline 任意直线 axline([0,0],[1,1]) 绘制穿过 (0,0) 和 (1,1) 的直线

(2)添加网格

复制代码
ax.grid(True)  # 显示灰色网格
  • 进阶参数:axis='x' 只显示 x 轴网格,linestyle='--' 修改虚线样式。

4.轴与标题的设置(规范坐标)

利用 ax 对象可以精准控制坐标轴的刻度、范围和名称:

复制代码
ax.set_xscale('log')      # 设置x轴为对数坐标(普通坐标为linear)
ax.set_title('子标题1')   # 设置子图标题
ax.set_xlabel('对数坐标') # 设置x轴标签
ax.set_ylabel('普通坐标') # 设置y轴标签

效果对比

  • 左图 :x 轴采用对数刻度(10^0, 10^1, 10^2...),数据增长呈指数级展示。
  • 右图:x 轴采用普通线性刻度,数据呈直线增长。

5.注释与标注

除了基础绘图,ax 支持添加丰富的文本和箭头注释:

(1)绘制箭头

复制代码
ax.arrow(x=0, y=0, dx=1, dy=1, head_width=0.03, facecolor='red')
  • dx/dy:箭头的长度和方向。
  • head_width/head_length:箭头头部的大小。

(2)添加普通文字

复制代码
ax.text(x=0, y=0, s='这是一段文字', color='green', rotation=70)
  • rotation:文字旋转角度。

(3)带箭头的注释(最常用)

复制代码
ax.annotate('这是中点', 
            xy=(0.5, 0.5),    # 箭头指向的位置
            xytext=(0.8, 0.2),# 文字位置
            arrowprops=dict(facecolor='yellow', edgecolor='black')) # 箭头样式

6.图例与位置控制(legend)

(1)基础用法

先在绘图时指定 label,再通过 ax.legend() 显示:

复制代码
ax.plot([1,2], [2,1], label="line1")
ax.plot([1,1], [1,2], label="line2")
ax.legend(loc=1)

(2)loc 参数对照表

string code 位置说明
best 0 最佳位置(自动避开数据重叠)
upper right 1 右上角(默认位置)
upper left 2 左上角
lower left 3 左下角
lower right 4 右下角
right 5 右侧(垂直居中)
center left 6 左侧居中
center right 7 右侧居中
lower center 8 底部居中
upper center 9 顶部居中
center 10 正中心
相关推荐
绛橘色的日落(。・∀・)ノ1 天前
Matplotlib 第二章 艺术画笔见乾坤
matplotlib
MediaTea5 天前
人工智能通识课:Matplotlib 绘图基础
人工智能·matplotlib
MediaTea7 天前
Matplotlib 常用函数手册
matplotlib
badhope12 天前
Matplotlib实战30例:全类型图表代码库
人工智能·python·plotly·github·matplotlib
badhope12 天前
最小二乘与最速下降法实战解析
人工智能·机器学习·plotly·github·matplotlib
badhope13 天前
Docker入门到实战全攻略
linux·python·docker·github·matplotlib
李昊哲小课14 天前
matplotlib多子图与复杂布局实战
python·数据分析·matplotlib·数据可视化
李昊哲小课16 天前
matplotlib_tutorial
数据分析·matplotlib·数据可视化