Matplotlib-多图布局与网格显示

Matplotlib-多图布局与网格显示

    • 一、多图布局的核心组件
    • 二、基础布局:plt.subplots()快速创建网格
      • 1. 均等分网格
      • 2. 不等分网格(指定比例)
    • 三、进阶布局:GridSpec实现复杂嵌套
      • 1. 跨行列布局
      • 2. 嵌套GridSpec
    • 四、实用技巧:布局美化与一致性
      • 1. 统一坐标轴范围与标签
      • 2. 全局样式统一
      • 3. 动态调整子图数量
    • 五、常见问题与解决方案
      • 1. 子图重叠或标签被截断
      • 2. 中文显示乱码
      • 3. 保存图像时布局错乱

在数据分析与可视化中,单一图表往往难以全面呈现复杂信息,将多个相关图表按逻辑布局组合,既能对比数据特征,又能揭示潜在关联。Matplotlib提供了灵活的多图布局工具,从简单的行列排列到复杂的嵌套网格,满足从基础分析到专业报告的多样化需求。

一、多图布局的核心组件

Matplotlib的多图布局基于画布(Figure)子图(Axes) 两大组件:

  • 画布(Figure):所有图表的容器,相当于绘图的“纸张”,通过plt.figure()创建。
  • 子图(Axes):画布上的单个图表区域,包含坐标轴、标题等元素,通过plt.subplot()plt.subplots()创建。

多图布局的本质是在画布上规划子图的位置与尺寸,关键参数包括:

  • 行数(nrows)列数(ncols):定义子图的网格结构。
  • 间距(hspace/wspace):控制子图之间的垂直/水平距离。
  • 跨度(colspan/rowspan):允许子图跨越多行或多列(复杂布局必备)。

二、基础布局:plt.subplots()快速创建网格

plt.subplots(nrows, ncols)是创建规则网格布局的首选方法,一次性生成所有子图并返回子图数组,适合行列整齐的布局。

1. 均等分网格

创建2行2列的均等分网格,展示4个相关图表:

import numpy as np
import matplotlib.pyplot as plt# 创建2x2网格的画布和子图数组
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))  # 画布大小10x8英寸# 生成示例数据
x = np.linspace(0, 2*np.pi, 100)
data = [np.sin(x), np.cos(x), np.sin(2*x), np.cos(2*x)]
titles = ['sin(x)', 'cos(x)', 'sin(2x)', 'cos(2x)']# 遍历子图数组并绘图
for i, ax in enumerate(axes.flat):  # axes.flat将二维数组转为一维迭代器ax.plot(x, data[i])ax.set_title(titles[i], fontsize=10)ax.grid(alpha=0.3)# 调整子图间距(hspace垂直间距,wspace水平间距)
plt.subplots_adjust(hspace=0.3, wspace=0.2)
plt.suptitle("Trigonometric Functions", fontsize=14, y=0.95)  # 总标题
plt.show()
  • axes.flat简化了子图的批量处理,避免嵌套循环。
  • plt.subplots_adjust()用于微调间距,确保图表不重叠。

2. 不等分网格(指定比例)

通过gridspec_kw参数设置行列比例,实现非均等分布局:

# 创建1行2列网格,列宽比例为3:1
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10, 4),gridspec_kw={'width_ratios': [3, 1]})# 左侧绘制曲线
ax1.plot(x, np.sin(x), color='blue')
ax1.set_title("sin(x) Curve")
ax1.grid(alpha=0.3)# 右侧绘制直方图
ax2.hist(np.sin(x), bins=20, orientation='horizontal', color='orange')
ax2.set_title("Distribution")
ax2.grid(alpha=0.3)plt.tight_layout()  # 自动调整布局,替代subplots_adjust
plt.show()
  • width_ratios控制列宽比例,height_ratios控制行高比例(适用于多行布局)。
  • plt.tight_layout()自动优化间距,是快速布局的实用工具。

三、进阶布局:GridSpec实现复杂嵌套

当需要跨行列的子图(如合并单元格的Excel表格),matplotlib.gridspec.GridSpec是更强大的工具,支持子图跨度与精细尺寸控制。

1. 跨行列布局

创建包含跨列子图的复杂网格:

from matplotlib.gridspec import GridSpec# 创建3行3列的GridSpec,设置行高和列宽比例
gs = GridSpec(3, 3, figure=plt.figure(figsize=(10, 8)),height_ratios=[1, 1, 1],width_ratios=[1, 1, 1],hspace=0.3, wspace=0.2)# 分配子图位置(行索引start:end, 列索引start:end)
ax1 = plt.subplot(gs[0, :])  # 第0行,横跨所有列(0-2)
ax2 = plt.subplot(gs[1, 0:2])  # 第1行,列0-1
ax3 = plt.subplot(gs[1, 2])  # 第1行,列2
ax4 = plt.subplot(gs[2, 0])  # 第2行,列0
ax5 = plt.subplot(gs[2, 1:3])  # 第2行,列1-2# 绘图示例
ax1.plot(x, np.sin(x), color='red')
ax1.set_title("Full Width Plot (Row 0)")ax2.scatter(np.random.rand(50), np.random.rand(50), alpha=0.6)
ax3.bar(['A', 'B', 'C'], [3, 5, 2], color='green')
ax4.hist(np.random.normal(0, 1, 100), bins=15)
ax5.plot(x, np.cos(x), color='purple')# 隐藏冗余坐标轴标签
for ax in [ax2, ax3, ax4, ax5]:ax.tick_params(axis='x', labelsize=8)ax.tick_params(axis='y', labelsize=8)plt.tight_layout()
plt.show()
  • gs[i, j]中,ij支持切片(start:end),表示跨多个索引。
  • 适合创建“标题图+细节图”的层级布局,突出核心信息。

2. 嵌套GridSpec

在子图中嵌套另一个GridSpec,实现更复杂的层级结构:

fig = plt.figure(figsize=(12, 8))# 外层GridSpec:2行1列
outer_gs = GridSpec(2, 1, figure=fig, height_ratios=[1, 2], hspace=0.4)# 上层子图:简单曲线
ax_top = fig.add_subplot(outer_gs[0])
ax_top.plot(x, np.sin(x), color='blue')
ax_top.set_title("Main Trend")# 下层嵌套GridSpec:1行2列
inner_gs = GridSpecFromSubplotSpec(1, 2, subplot_spec=outer_gs[1], wspace=0.3)
ax_bottom_left = fig.add_subplot(inner_gs[0])
ax_bottom_right = fig.add_subplot(inner_gs[1])ax_bottom_left.plot(x, np.sin(x)*0.5, color='orange')
ax_bottom_left.set_title("Zoomed In")
ax_bottom_right.plot(x, np.sin(x)+1, color='green')
ax_bottom_right.set_title("Shifted Up")plt.tight_layout()
plt.show()
  • GridSpecFromSubplotSpec用于在内层子图中创建新网格,继承外层布局的位置。
  • 适合展示“总览+分面”的数据分析场景(如地图的全局+局部放大)。

四、实用技巧:布局美化与一致性

1. 统一坐标轴范围与标签

多图对比时,保持坐标轴范围一致可避免视觉误导:

fig, axes = plt.subplots(2, 2, figsize=(10, 8))
data = [np.sin(x), np.sin(x)+1, np.sin(x)*2, np.sin(x)-1]for i, ax in enumerate(axes.flat):ax.plot(x, data[i])ax.set_ylim(-2.5, 2.5)  # 统一y轴范围ax.set_xlim(0, 2*np.pi)  # 统一x轴范围# 共享x轴(仅显示底部子图的x标签)
for ax in axes[:-1, :].flat:ax.set_xticklabels([])# 共享y轴(仅显示左侧子图的y标签)
for ax in axes[:, 1:].flat:ax.set_yticklabels([])plt.tight_layout()
plt.show()
  • sharex=Truesharey=Trueplt.subplots()中可快速实现轴共享:
    fig, axes = plt.subplots(2, 2, figsize=(10, 8), sharex=True, sharey=True)
    

2. 全局样式统一

通过plt.rcParams设置全局样式,确保多图风格一致:

# 设置全局字体和线条样式
plt.rcParams.update({'font.family': 'SimHei',  # 支持中文'axes.labelsize': 10,'axes.titlesize': 12,'lines.linewidth': 1.5,'grid.linestyle': ':'
})# 绘图时自动应用全局样式
fig, ax = plt.subplots()
ax.plot(x, np.sin(x))
ax.set_title("中文标题测试")  # 正常显示中文
plt.show()

3. 动态调整子图数量

根据数据量动态生成子图(如批量展示10个样本的图像):

n_samples = 6  # 动态数据量
n_cols = 3  # 固定列数
n_rows = (n_samples + n_cols - 1) // n_cols  # 计算行数(向上取整)fig, axes = plt.subplots(n_rows, n_cols, figsize=(n_cols*4, n_rows*3))for i in range(n_samples):row = i // n_colscol = i % n_colsaxes[row, col].plot(x, np.sin(x + i*0.5))axes[row, col].set_title(f"Sample {i+1}")# 隐藏多余子图(若样本数不足n_rows*n_cols)
for i in range(n_samples, n_rows*n_cols):row = i // n_colscol = i % n_colsfig.delaxes(axes[row, col])plt.tight_layout()
plt.show()

五、常见问题与解决方案

1. 子图重叠或标签被截断

  • 解决方案:使用plt.tight_layout()plt.subplots_adjust(top=0.9)调整顶部留白。
  • 极端情况:减小figsize或字体大小(plt.rcParams['font.size'] = 8)。

2. 中文显示乱码

  • 解决方案:设置全局字体为支持中文的字体(如SimHeiWenQuanYi Micro Hei):
    plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
    

3. 保存图像时布局错乱

  • 解决方案:保存时添加bbox_inches='tight'参数:
    plt.savefig("multi_plot.png", dpi=300, bbox_inches='tight')
    

总结:Matplotlib多图布局的核心原则

  1. 简洁优先:规则网格用plt.subplots(),复杂跨列用GridSpec
  2. 逻辑清晰:按数据关联度排列,同类图表保持样式一致。
  3. 视觉平衡:避免子图大小差异过大,关键图表可占据更大空间。
  4. 自动化适配:利用tight_layout()和动态计算行数,减少手动调整。

That’s all, thanks for reading~~
觉得有用就点个赞、收进收藏夹吧!关注我,获取更多干货~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88414.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88414.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GitHub上优秀的开源播放器项目介绍及优劣对比

ExoPlayer 项目地址:https://github.com/google/ExoPlayer 特点: 由Google开发,支持广泛的视频格式和流媒体传输协议,如DASH、HLS、SmoothStreaming。 提供灵活的媒体源架构和高级特性,如动态自适应流播放。 开发者可以轻松扩展和定制播放器组件,适应特定需求。 优点: 功…

react打包发到线上报错Minified React error #130

开发过程中遇到一个问题,记录一下 本地打包发布正常,发测试环境正常,可是通过Jenkins打包发布线上报错 报错信息 index-67fbbd81.js:39 Error: Minified React error #130; visit https://reactjs.org/docs/error-decoder.html?invariant130…

微服务项目远程调用时的负载均衡是如何实现的?

负载均衡概述 负载均衡是微服务架构中的核心组件,用于将请求合理分配到多个服务实例上,提高系统的可用性和性能。负载均衡的分类 负载均衡大致可以分为两类 1. 服务端负载均衡 实现位置:独立部署的负载均衡服务器(位于客户端和服务…

【中文核心期刊推荐】中国农业科技导报

《中国农业科技导报》是中国科技核心期刊,也是北京大学图书馆“中文核心期刊要目总览”收录的期刊。它是由中国农村技术开发中心主办,全面为科教兴农服务的综合性农业学术期刊。《中国农业科技导报》是中国农业科学院生物技术研究所承办的&a…

php 如何通过mysqli操作数据库?

在PHP中,mysqli(MySQL Improved Extension)是操作MySQL数据库的扩展库,提供了面向对象和过程式两种风格。以下是mysqli的基本操作方法: 1. 连接数据库 面向对象风格 $mysqli new mysqli(localhost, username, passwor…

c/c++拷贝函数

memcpy()函数概要原型void * memcpy ( void * dest, const void * src, size_t num );功能memcpy()会复制 src 所指的内存内容的前 num 个字节到 dest所指的内存地址上(memcpy()并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用…

HTTP核心基础详解(附实战要点)

目录 一图胜千言:HTTP核心机制图解​编辑 一、HTTP本质:通信的桥梁 二、五大核心特性解析 三、HTTP头部:隐藏的控制中心 四、连接管理:性能关键点 开发者必知实践技巧 一图胜千言:HTTP核心机制图解 一、HTTP本质…

华为静态路由配置

问题描述:针对两台笔记本和两个路由器在不同的网段场景中,对两个路由器进行静态路由配置。下面以如下场景为例,介绍详细配置过程。配置步骤: 1、对每个路由器的接口下配置IP地址 [huawei]interface gx/x/x [huawei-interface]ip a…

闲庭信步使用图像验证平台加速FPGA的开发:第八课——图像数据的行缓存

(本系列只需要modelsim即可完成数字图像的处理,每个工程都搭建了全自动化的仿真环境,只需要双击文件就可以完成整个的仿真,大大降低了初学者的门槛!!!!如需要该系列的工程文件请关注…

经典排序算法

文章目录前言1. 排序的基本概念1.1 排序是什么?1.2 常见的排序算法概览2. 常见排序算法的实现2.1 插入排序 (Insertion Sort)2.1.1 基本思想2.1.2 直接插入排序2.1.3 希尔排序 (Shell Sort)2.2 选择排序 (Selection Sort)2.2.1 直接选择排序2.2.2 堆排序 (Heap Sort…

RabbitMQ 消息队列:从入门到Spring Boot实战

RabbitMQ 作为一款开源的、基于 AMQP(Advanced Message Queuing Protocol)协议实现的消息代理,凭借其强大的功能、灵活的路由机制以及出色的性能,在业界得到了广泛的应用。无论是处理高并发订单、异步通知、日志收集还是系统解耦&…

代账行业数字化破局:从“知道”到“做到”,三步走稳赢!

认知!降本!增收!数字化!——这不仅是口号,更是代账行业在激烈竞争和时代变化中生存发展的关键。很多代账同行其实都明白趋势,也知道大概该怎么做。但问题卡在第一步:不知道怎么开始,…

Mac 电脑crontab执行定时任务【Python 实战】

1、crontab -e 编辑定时任务列表 crontab -e查看当前定时任务列表,长按 i 编辑,编辑完之后按 esc 退出编辑,然后输入:wq 保存并提出。 如下: (base) charles@zl ~ % crontab -e58 15 * * * /Library/Frameworks/Python.framework/Versions/3.8/bin/python3 /Users/charle…

go go go 出发咯 - go web开发入门系列(三) 项目基础框架搭建与解读

go go go 出发咯 - go web开发入门系列(三) 项目基础框架搭建与解读 往期回顾 go go go 出发咯 - go web开发入门系列(一) helloworldgo go go 出发咯 - go web开发入门系列(二) Gin 框架实战指南 前言 如…

【字节跳动】数据挖掘面试题0014:SQL中count(1), count(*), count(列)区别

文章大纲SQL 中 count(1)、count(*)、count(某列) 的区别一、核心定义与行为差异二、示例说明差异三、性能差异与优化四、适用场景建议五、面试应答要点六、索引扫描与全表扫描1. 索引扫描的触发条件2. 全表扫描的适用场景3. 常见面试问题点Q1:索引扫描一定比全表扫…

Linux面试问题-软件测试

1、你在上一家公司常用的Linux命令有哪些?答:使用vim/vi编辑文件,使用cat,more,less,head查看文件,使用grep过滤日志中的error,使用ps查看进程,使用top查看实时进程,netstat查看端口…

时序数据库的存储之道:从数据特性看技术要点

时序数据的独特挑战时序数据(Time-Series Data)是指按时间顺序记录的一系列数据点,在物联网、金融、工业监控等领域无处不在。与传统数据相比,时序数据具有几个鲜明特点:时间导向性:每个数据点都带有精确的时间戳高写入量&#xf…

【vim中替换】

vim中替换1 : s/在Vim中经常高频使用到的命令:1 : s/ :s 命令的基本语法是 :[range]s/{pattern}/{string}/[flags],其中: • [range] 是可选的范围,用于指定替换的行范围。例如,% 表示全文,10,…

Qt实战:使用QSqlDatabase连接MySQL,并实现增删改查

文章目录一、创建数据表二、连接MySQL数据库三、封装成一个完整的轻量级 ORM 风格类四、实现派生具体模型类五、支持多线程连接池 ORM 事务封装一、创建数据表 数据库名: 我们先创建一个数据库,名字叫 game_db: CREATE DATABASE IF NOT E…

Python脚本保护工具库之pyarmor使用详解

概要 PyArmor是一个专门为Python代码提供加密保护的第三方库,旨在解决Python源代码易被反编译和泄露的安全问题。作为一种动态代码保护工具,PyArmor能够对Python脚本进行混淆和加密处理,有效防止源代码被恶意获取、分析或篡改。该库特别适用于商业软件开发、知识产权保护和…