Skip to content

Matplotlib 与数据可视化

Matplotlib 是 Python 可视化的奠基者——几乎所有 Python 图表库(Seaborn、Pandas 内置绘图)都基于它构建。本页带你从第一张折线图走到多子图仪表盘。前置阅读:NumPy 科学计算入门。

Matplotlib 由 John Hunter 于 2003 年创建,最初是为了在 Python 中复现 MATLAB 的绘图能力(名字就来自 MATplotlib PLOT LIB)。它是一个底层绘图引擎,能画从简单折线图到复杂科学论文插图的几乎所有二维图表,精细到每一个像素都可控制。

它的设计哲学是渐进式控制:用三行代码画一张能看的图,但如果你想调整字号、坐标轴刻度、图例位置、配色方案,每一处都可以精确定制。这种”简单的事情简单做,复杂的事情能做到”的特性,使它成为学术论文、数据报告、Jupyter 笔记本中最常用的可视化工具。

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 做图像对比测试,可能需要适当放宽容差。

Terminal window
# 安装 Matplotlib
pip 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。

Matplotlib 的世界观非常直观:Figure 是画板(一整块画布),Axes 是画纸(画板上一张张具体的图)。一块画板上可以放多张画纸(子图),每张画纸有自己独立的坐标轴、标题、数据。

  • Figure:最外层容器,控制整体大小、背景色、输出文件。
  • Axes:单张图表,包含 x 轴、y 轴、数据线、标题等所有元素。注意 Axes(复数)不是 Axis(坐标轴),一字之差。
  • Artist:你在图上看到的一切元素(线条、文字、图例)都是 Artist(艺术家对象)——Matplotlib 用”艺术家在画纸上作画”的比喻来组织所有可视元素。

典型流程是:创建 Figure 和 Axes → 在 Axes 上画数据(plot、scatter、hist)→ 添加标题、标签、图例 → 显示或保存。

Matplotlib 有两套 API:Pyplot 接口(plt.plot()、plt.title(),简单快捷,适合单图)和面向对象接口(fig, ax = plt.subplots(); ax.plot(),精确控制,适合多子图和复杂图表)。初学用 Pyplot,进阶务必转向面向对象写法。

打个比方:Pyplot 接口像自动挡——简单但控制力有限;面向对象接口像手动挡——操作更多但你能精确控制每一个齿轮。

数据可视化的一个常被忽视的维度是无障碍性——你的图表是否对色觉障碍(约影响全球 8% 的男性)读者友好?Matplotlib 3.11 新增了 Petroff 色谱等方案来解决这个问题。选择配色时应优先考虑:

  • viridis / plasma / inferno / magma:感知均匀的连续配色(数值越大颜色越深,人眼感受呈线性变化)。
  • coolwarm:双向配色,适合表达正负偏差。
  • Petroff 色谱(3.11 新增):离散的类别配色,最多 10 种颜色,色盲友好。
import matplotlib.pyplot as plt
import 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 plt
import 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 plt
import 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()

子图示例:三角函数、直方图、柱状图、面积图

import matplotlib.pyplot as plt
import 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,标准差10
class_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 plt
import 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()

热力图示例:分类混淆矩阵

Matplotlib 内置了多种样式表(stylesheet),一行代码就能切换整体视觉风格:

import matplotlib.pyplot as plt
import 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()

ggplot 样式效果

dark_background 样式效果

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') 一行就能让默认图表变得专业。
  • 数据探索性分析:拿到数据先画分布直方图、散点矩阵,快速发现异常值和规律,比纯看数字高效得多。
  • 模型训练过程可视化:画出训练过程中 loss(损失函数值)和准确率的折线图,判断是否过拟合、何时早停。详见模型评估。
  • 学术论文插图:Matplotlib 精细到像素的控制能力,使它能产出达到期刊发表质量的图表。配合 LaTeX 渲染公式,是科研标配。
  • 混淆矩阵与特征相关性热力图:用 imshow 可视化二维矩阵数据,直观展示分类器的错误分布或特征间相关程度。
  • 聚类结果可视化:将高维数据降维到二维后用散点图着色,直观展示聚类效果。详见聚类分析。
  • 数据报告与仪表盘:多子图拼合成综合面板,配合 savefig 导出图片嵌入报告。
特性MatplotlibSeabornPlotlyPyEcharts
定位底层绘图引擎统计可视化上层封装交互式图表交互式图表(百度)
交互性静态(可内嵌)静态强交互(悬停/缩放)强交互
输出格式PNG / PDF / SVG同 MatplotlibHTML / 网页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 — 交互式可视化库,适合制作可悬停、可缩放的网页图表和数据仪表盘。