Matplotlib 与数据可视化
Matplotlib 是 Python 可视化的奠基者——几乎所有 Python 图表库(Seaborn、Pandas 内置绘图)都基于它构建。本页带你从第一张折线图走到多子图仪表盘。前置阅读:NumPy 科学计算入门。
这个库是什么
Section titled “这个库是什么”Matplotlib 由 John Hunter 于 2003 年创建,最初是为了在 Python 中复现 MATLAB 的绘图能力(名字就来自 MATplotlib PLOT LIB)。它是一个底层绘图引擎,能画从简单折线图到复杂科学论文插图的几乎所有二维图表,精细到每一个像素都可控制。
它的设计哲学是渐进式控制:用三行代码画一张能看的图,但如果你想调整字号、坐标轴刻度、图例位置、配色方案,每一处都可以精确定制。这种”简单的事情简单做,复杂的事情能做到”的特性,使它成为学术论文、数据报告、Jupyter 笔记本中最常用的可视化工具。
2025-2026 最新进展(v3.11)
Section titled “2025-2026 最新进展(v3.11)”Matplotlib 在 2025-2026 年发布了重要的 3.11 版本(2026 年 7 月发布 3.11.1),带来了自 3.0 以来最大的更新:
- 文本与字体渲染全面重写:通过集成 libraqm、HarfBuzz(文本整形引擎)、SheenBidi(双向文本处理)和更新的 FreeType(字体光栅化引擎),实现了对现代字体特性的完整支持,包括所有语言的国际化渲染(阿拉伯语、日语、希伯来语等从右到左或混合方向的文字不再乱码)。这是本次更新的最大变化。
- 无障碍配色方案:新增 Petroff 色谱等感知均匀且色盲友好的颜色序列,适用于多类别图表(最多 10 类),让色觉障碍读者也能区分不同数据系列。
- 3D 坐标轴改进:3D 绘图功能得到大幅增强,包括更好的
tight_layout支持、坐标轴反转修复、宽高比控制改进等。 - 性能优化:渲染管线优化,尤其是大规模散点图和等高线图的绘制速度。
- Python 3.14 支持:包括自由线程(free-threaded,即无 GIL 模式)版本的 wheel(预编译二进制包),走在 Python 生态最前沿。
- 灵活的图形管理:新的 Figure 管理接口让多窗口交互式绘图更可靠。
兼容性提示:由于字体渲染引擎的全面升级,3.11 生成的文字在像素级别上可能与旧版本略有差异。如果你用 Matplotlib 做图像对比测试,可能需要适当放宽容差。
安装与环境配置
Section titled “安装与环境配置”# 安装 Matplotlibpip install matplotlib
# 推荐搭配 NumPy(生成数据)和 Pandas(数据处理)一起使用pip install matplotlib numpy pandas
# 验证安装python -c "import matplotlib; print(matplotlib.__version__)"在 Jupyter Notebook 中,在文件开头加一行 %matplotlib inline 即可在单元格内显示图表。脚本中用 plt.show() 弹出窗口查看,或用 plt.savefig('图.png') 保存文件。导入约定写为 import matplotlib.pyplot as plt。
Figure 与 Axes:画板与画纸
Section titled “Figure 与 Axes:画板与画纸”Matplotlib 的世界观非常直观:Figure 是画板(一整块画布),Axes 是画纸(画板上一张张具体的图)。一块画板上可以放多张画纸(子图),每张画纸有自己独立的坐标轴、标题、数据。
- Figure:最外层容器,控制整体大小、背景色、输出文件。
- Axes:单张图表,包含 x 轴、y 轴、数据线、标题等所有元素。注意 Axes(复数)不是 Axis(坐标轴),一字之差。
- Artist:你在图上看到的一切元素(线条、文字、图例)都是 Artist(艺术家对象)——Matplotlib 用”艺术家在画纸上作画”的比喻来组织所有可视元素。
典型流程是:创建 Figure 和 Axes → 在 Axes 上画数据(plot、scatter、hist)→ 添加标题、标签、图例 → 显示或保存。
面向对象 vs Pyplot 接口
Section titled “面向对象 vs Pyplot 接口”Matplotlib 有两套 API:Pyplot 接口(plt.plot()、plt.title(),简单快捷,适合单图)和面向对象接口(fig, ax = plt.subplots(); ax.plot(),精确控制,适合多子图和复杂图表)。初学用 Pyplot,进阶务必转向面向对象写法。
打个比方:Pyplot 接口像自动挡——简单但控制力有限;面向对象接口像手动挡——操作更多但你能精确控制每一个齿轮。
配色与无障碍设计
Section titled “配色与无障碍设计”数据可视化的一个常被忽视的维度是无障碍性——你的图表是否对色觉障碍(约影响全球 8% 的男性)读者友好?Matplotlib 3.11 新增了 Petroff 色谱等方案来解决这个问题。选择配色时应优先考虑:
viridis/plasma/inferno/magma:感知均匀的连续配色(数值越大颜色越深,人眼感受呈线性变化)。coolwarm:双向配色,适合表达正负偏差。- Petroff 色谱(3.11 新增):离散的类别配色,最多 10 种颜色,色盲友好。
架构与工作流
Section titled “架构与工作流”例 1:折线图——最基础的图表
Section titled “例 1:折线图——最基础的图表”import matplotlib.pyplot as pltimport numpy as np
# 生成模拟数据:某城市一年气温变化months = np.arange(1, 13)temp = np.array([2, 5, 11, 18, 23, 28, 30, 29, 24, 17, 9, 3])
plt.figure(figsize=(8, 4)) # 设置画板大小(宽8英寸,高4英寸)plt.plot(months, temp, # x 轴数据, y 轴数据 color='#E91E63', # 线条颜色 marker='o', # 数据点标记为圆点 linewidth=2, # 线宽 label='月平均气温') # 图例文字plt.xlabel('月份') # x 轴标签plt.ylabel('温度 (°C)') # y 轴标签plt.title('2024 年全年气温趋势')plt.legend() # 显示图例plt.grid(True, alpha=0.3) # 半透明网格线plt.show()
例 2:散点图——观察两个变量的关系
Section titled “例 2:散点图——观察两个变量的关系”import matplotlib.pyplot as pltimport numpy as np
# 模拟数据:房屋面积与价格的关系np.random.seed(42)area = np.random.uniform(50, 200, 100) # 100套房的面积price = area * 5 + np.random.randn(100) * 80 # 面积越大价格越高,加噪声
plt.figure(figsize=(7, 5))plt.scatter(area, price, c=price, # 点的颜色随价格变化(颜色映射) cmap='viridis', # 配色方案:感知均匀,色盲友好 alpha=0.7, # 半透明,重叠区域更深 edgecolors='white') # 白色描边plt.colorbar(label='价格 (万元)') # 颜色条plt.xlabel('面积 (m²)')plt.ylabel('价格 (万元)')plt.title('房屋面积与价格关系')plt.show()
例 3:子图(Subplot)——面向对象接口
Section titled “例 3:子图(Subplot)——面向对象接口”import matplotlib.pyplot as pltimport numpy as np
# 面向对象接口:一次创建多张子图的画板fig, axes = plt.subplots(2, 2, figsize=(10, 8)) # 2行2列共4张子图x = np.linspace(0, 2 * np.pi, 100)
# 左上:正弦与余弦曲线叠加axes[0, 0].plot(x, np.sin(x), label='sin', color='steelblue')axes[0, 0].plot(x, np.cos(x), label='cos', color='coral')axes[0, 0].legend(); axes[0, 0].set_title('三角函数')
# 右上:直方图(数据分布)data = np.random.randn(1000)axes[0, 1].hist(data, bins=30, color='mediumpurple', edgecolor='white')axes[0, 1].set_title('正态分布直方图')
# 左下:柱状图categories = ['A', 'B', 'C', 'D']values = [23, 45, 12, 67]axes[1, 0].bar(categories, values, color=['#4CAF50', '#2196F3', '#FF9800', '#E91E63'])axes[1, 0].set_title('各类别数值对比')
# 右下:面积图axes[1, 1].fill_between(x, np.sin(x), alpha=0.3, color='teal')axes[1, 1].set_title('正弦曲线面积图')
plt.tight_layout() # 自动调整子图间距,避免重叠plt.show()
例 4:直方图与中文显示配置
Section titled “例 4:直方图与中文显示配置”import matplotlib.pyplot as pltimport numpy as np
# 中文字体配置(解决中文乱码问题,Windows/Linux 常见需求)# Matplotlib 默认字体不含中文字符,必须手动指定系统中可用的中文字体plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体显示中文(Windows)# Linux 用户可能需要改为:['WenQuanYi Micro Hei'] 或 ['Noto Sans CJK SC']# macOS 用户可以改为:['Arial Unicode MS']plt.rcParams['axes.unicode_minus'] = False # 正常显示负号(中文字体常导致负号变方块)
# 模拟两个班级的考试成绩class_a = np.random.normal(75, 10, 200) # A班:均值75,标准差10class_b = np.random.normal(70, 15, 200) # B班:均值70,标准差15
plt.figure(figsize=(8, 5))plt.hist([class_a, class_b], bins=20, label=['A 班', 'B 班'], color=['steelblue', 'coral'], alpha=0.7, edgecolor='white')plt.xlabel('分数')plt.ylabel('人数')plt.title('两个班级成绩分布对比')plt.legend()plt.savefig('成绩分布.png', dpi=150, bbox_inches='tight') # 保存为高清图片plt.show()
3.11 字体渲染升级提示:如果你使用 Matplotlib 3.11+,得益于全新的 libraqm + HarfBuzz 字体引擎,复杂文字(混合中英文、特殊符号、数学公式)的渲染效果会显著提升。如果你之前的图表中有文字间距不均匀或某些字符显示异常的问题,升级后很可能自动修复。
例 5:热力图——机器学习中的常用可视化
Section titled “例 5:热力图——机器学习中的常用可视化”热力图(Heatmap)用颜色深浅表示二维矩阵中数值的大小,在混淆矩阵可视化、特征相关性分析等场景极为常用:
import matplotlib.pyplot as pltimport numpy as np
# 模拟一个混淆矩阵(3 类分类任务)labels = ['猫', '狗', '鸟']confusion = np.array([[85, 10, 5], [8, 87, 5], [3, 7, 90]])
fig, ax = plt.subplots(figsize=(6, 5))# imshow 把二维数组显示为图像,颜色映射到数值大小im = ax.imshow(confusion, cmap='Blues')
# 添加颜色条plt.colorbar(im, label='样本数')
# 设置刻度标签ax.set_xticks(range(3)); ax.set_yticks(range(3))ax.set_xticklabels(labels); ax.set_yticklabels(labels)ax.set_xlabel('预测类别'); ax.set_ylabel('真实类别')ax.set_title('分类混淆矩阵')
# 在每个格子里写上数值for i in range(3): for j in range(3): # 文字颜色:深色背景用白色文字,浅色背景用黑色文字 color = 'white' if confusion[i, j] > 50 else 'black' ax.text(j, i, str(confusion[i, j]), ha='center', va='center', color=color)
plt.tight_layout()plt.show()
例 6:使用样式表快速美化
Section titled “例 6:使用样式表快速美化”Matplotlib 内置了多种样式表(stylesheet),一行代码就能切换整体视觉风格:
import matplotlib.pyplot as pltimport numpy as np
x = np.linspace(0, 10, 100)
# 查看所有可用样式print(plt.style.available)# ['seaborn-v0_8-darkgrid', 'ggplot', 'bmh', 'dark_background', ...]
# 使用 ggplot 风格(类似 R 语言 ggplot2 的经典外观)with plt.style.context('ggplot'): fig, ax = plt.subplots(figsize=(8, 4)) ax.plot(x, np.sin(x), label='sin(x)', linewidth=2) ax.plot(x, np.cos(x), label='cos(x)', linewidth=2) ax.set_title('使用 ggplot 样式') ax.legend() plt.show()
# 使用暗色背景(适合深色主题的演示文稿)with plt.style.context('dark_background'): fig, ax = plt.subplots(figsize=(8, 4)) ax.plot(x, np.sin(x), label='sin(x)', color='cyan', linewidth=2) ax.set_title('使用 dark_background 样式') ax.legend() plt.show()

常用 API 速查
Section titled “常用 API 速查”| API | 用途 | 示例 |
|---|---|---|
plt.figure(figsize=) | 创建画板 | plt.figure(figsize=(8,4)) |
plt.subplots(r,c) | 创建多子图 | fig, ax = plt.subplots(2,2) |
ax.plot(x,y) | 折线图 | ax.plot(x, np.sin(x)) |
ax.scatter(x,y) | 散点图 | ax.scatter(area, price) |
ax.bar(x,h) | 柱状图 | ax.bar(['A','B'],[1,2]) |
ax.barh(y,w) | 水平柱状图 | ax.barh(cats, vals) |
ax.hist(data,bins) | 直方图 | ax.hist(scores, bins=20) |
ax.imshow(data) | 热力图 / 图像 | ax.imshow(confusion_matrix, cmap='Blues') |
ax.fill_between(x,y) | 面积图 | ax.fill_between(x, y, alpha=0.3) |
ax.contour(X,Y,Z) | 等高线图 | ax.contour(X, Y, Z, levels=20) |
ax.set_title(t) | 设置标题 | ax.set_title('销量趋势') |
ax.set_xlabel(t) | 设置 x 轴标签 | ax.set_xlabel('月份') |
ax.legend() | 显示图例 | ax.legend() |
plt.style.use(name) | 使用样式表 | plt.style.use('ggplot') |
plt.savefig(path) | 保存图片 | plt.savefig('fig.png', dpi=150) |
plt.tight_layout() | 自动调整间距 | plt.tight_layout() |
plt.colorbar() | 添加颜色条 | plt.colorbar(label='价格') |
- 中文乱码必踩坑:Matplotlib 默认不支持中文,图表中的中文字符会显示为方框。解决方法是在脚本开头设置
plt.rcParams['font.sans-serif'] = ['SimHei'](Windows)或['WenQuanYi Micro Hei'](Linux)。3.11 版本的字体引擎升级让更多 CJK(中日韩)字体能被正确识别和使用。 - 面向对象接口更适合实战:单张简单图用
plt.plot()即可;但凡涉及多子图、双 y 轴、精细刻度控制,一律用fig, ax = plt.subplots()的面向对象写法,否则全局状态混乱到难以排查。 - 配色不要用默认彩虹色:
plt.cm.jet虽然鲜艳但感知不均匀(相邻颜色人眼难以区分),色盲不友好。推荐用viridis、plasma、coolwarm等 Matplotlib 内置的现代配色方案,或 3.11 新增的 Petroff 色谱。 - 保存时用高 DPI:
plt.savefig('图.png', dpi=150)保存的图远比截屏清晰。论文用 300 dpi,网页用 150 dpi。bbox_inches='tight'能避免标签被裁剪。 - 图表类型匹配数据类型:趋势用折线图、关系用散点图、分布用直方图、比较用柱状图、占比用饼图——选错图表类型会误导读者。
- 避免 3D 图表:除非数据确实是三维的,否则 3D 柱状图、3D 饼图几乎总是让数据更难读,是典型的”花哨但无用”。3.11 虽然改进了 3D 坐标轴,但这条原则不变。
- 善用样式表:不需要逐个参数调整——
plt.style.use('seaborn-v0_8-darkgrid')一行就能让默认图表变得专业。
典型应用场景
Section titled “典型应用场景”- 数据探索性分析:拿到数据先画分布直方图、散点矩阵,快速发现异常值和规律,比纯看数字高效得多。
- 模型训练过程可视化:画出训练过程中 loss(损失函数值)和准确率的折线图,判断是否过拟合、何时早停。详见模型评估。
- 学术论文插图:Matplotlib 精细到像素的控制能力,使它能产出达到期刊发表质量的图表。配合 LaTeX 渲染公式,是科研标配。
- 混淆矩阵与特征相关性热力图:用
imshow可视化二维矩阵数据,直观展示分类器的错误分布或特征间相关程度。 - 聚类结果可视化:将高维数据降维到二维后用散点图着色,直观展示聚类效果。详见聚类分析。
- 数据报告与仪表盘:多子图拼合成综合面板,配合
savefig导出图片嵌入报告。
与同类工具对比
Section titled “与同类工具对比”| 特性 | Matplotlib | Seaborn | Plotly | PyEcharts |
|---|---|---|---|---|
| 定位 | 底层绘图引擎 | 统计可视化上层封装 | 交互式图表 | 交互式图表(百度) |
| 交互性 | 静态(可内嵌) | 静态 | 强交互(悬停/缩放) | 强交互 |
| 输出格式 | PNG / PDF / SVG | 同 Matplotlib | HTML / 网页 | HTML / 网页 |
| 统计图表 | 需手动计算 | 内置(一行画箱线图) | 需手动 | 内置多种 |
| 美观度(默认) | 一般(需调参/样式表) | 出色(默认好看) | 出色 | 出色 |
| 国际化支持 | 3.11 全面升级(libraqm) | 同 Matplotlib | 原生支持 | 原生支持 |
| 学习曲线 | 中等(API 庞大) | 低(基于 Matplotlib) | 中等 | 低 |
| 适用场景 | 论文 / 静态报告 | 数据分析快速出图 | 交互式仪表盘 | 网页数据看板 |
选择建议:快速数据分析用 Seaborn(基于 Matplotlib,一行画出好看的统计图);学术论文和静态报告用 Matplotlib(控制力最强);网页交互式可视化用 Plotly。
- Matplotlib 官方画廊:matplotlib.org/stable/gallery — 找到想画的图表类型,复制代码修改数据即可,是最实用的学习方式。
- Matplotlib 官方教程:matplotlib.org/stable/tutorials — 官方的入门到进阶教程,覆盖 Figure/Axes 模型、颜色、刻度等核心概念。
- Matplotlib 3.11 Release Notes:matplotlib.org/stable/users/release_notes — 了解 3.11 的字体引擎重写、无障碍配色等新特性的官方说明。
- Seaborn 官方文档:seaborn.pydata.org — 基于 Matplotlib 的统计可视化库,默认样式更美观,内置分布图、回归图、热力图等高级图表类型。
- Plotly Python 文档:plotly.com/python — 交互式可视化库,适合制作可悬停、可缩放的网页图表和数据仪表盘。