Matplotlib 超详细教程
Matplotlib 是 Python 最基础、最强大的数据可视化库之一,它功能强大,高度可定制,几乎可以绘制任何你想要的静态、动态和交互式图表。

目录
-
- Figure (画布)
- Axes (坐标系/子图)
- Axis (坐标轴)
- Artist (艺术家)
-
- 最简单的绘图流程
plt.show()的作用
-
- 折线图 (
plot) - 散点图 (
scatter) - 柱状图 (
bar,barh) - 直方图 (
hist) - 饼图 (
pie) - 箱线图 (
boxplot)
- 折线图 (
-
(图片来源网络,侵删)- 和标签 (
title,xlabel,ylabel) - 设置图例 (
legend) - 设置坐标轴范围 (
xlim,ylim) - 设置刻度和刻度标签 (
xticks,yticks) - 添加网格 (
grid) - 线条样式和标记
- 颜色设置
- 保存图片 (
savefig)
- 和标签 (
-
plt.subplot():简单网格布局plt.subplots():创建整个 Figure 和 AxesGridSpec:更灵活的复杂布局
-
- 添加文本 (
text,annotate) - 使用样式表 (
plt.style.use) - 配置参数 (
rcParams)
- 添加文本 (
核心概念:理解 Matplotlib 的结构
在开始绘图之前,理解 Matplotlib 的三个核心对象至关重要:

- Figure (画布):整个图表的窗口或页面,你可以把它想象成一个画板,你可以在上面画一个或多个图。
- Axes (坐标系/子图):这是 Figure 上的一个绘图区域,它包含了两个(或三个)Axis 对象、刻度、标签、标题等,一个 Figure 可以包含多个 Axes,我们通常所说的“图”指的就是一个 Axes。
- Axis (坐标轴):数据的坐标轴,包括 X 轴和 Y 轴,它负责定义数据域、数据 ticks 和 labels。
- Artist (艺术家):所有在 Figure 上可见的元素都是 Artist 的子类,包括 Figure, Axes, Axis, Line2D, Text 等,当你调用一个绘图函数时,它其实是在创建一个或多个 Artist 对象并将其添加到 Axes 上。
重要提示:Matplotlib 提供了两种主要的 API:
pyplot(OO) API:matplotlib.pyplot模块提供了一个类似 MATLAB 的接口,非常适合快速绘制简单的图表,它通过隐式地创建和管理 Figure 和 Axes 来简化操作,大多数初学者从这里开始。- 面向对象 API:更推荐用于复杂或自定义的图表,这种方式让你可以显式地获取和控制 Figure 和 Axes 对象,从而更灵活地进行操作。
本教程将主要介绍 pyplot API,并在适当的时候引入面向对象 API 的优势。
入门:绘制你的第一张图
确保你已经安装了 Matplotlib 和 NumPy(通常用于生成数据):
pip install matplotlib numpy
最简单的绘图流程
import matplotlib.pyplot as plt import numpy as plt # 1. 准备数据 x = np.linspace(0, 10, 100) # 生成 0 到 10 之间的 100 个点 y = np.sin(x) # 2. 创建图形并绘图 plt.plot(x, y) # 3. 显示图形 plt.show()
代码解释:
import matplotlib.pyplot as plt:导入 Matplotlib 的pyplot模块,并简写为plt,这是惯例。x = np.linspace(...): 使用 NumPy 创建一组均匀分布的数据点,作为 X 轴数据。y = np.sin(x): 计算每个 x 点对应的正弦值,作为 Y 轴数据。plt.plot(x, y): 这是核心绘图函数,它会根据提供的数据自动创建一个 Figure 和一个 Axes,并在 Axes 上绘制一条折线。plt.show(): 将图形显示出来,在 Jupyter Notebook 或类似环境中,这步通常可以省略,因为图表会自动渲染。
plt.show() 的作用
plt.show() 会启动一个事件循环,打开一个图形窗口并等待你关闭它,在一个 Python 脚本中,plt.show() 之前所有的绘图命令都会被缓存起来,直到 plt.show() 被调用,它们才会被一次性渲染出来,这意味着你可以先定义多个图表,最后再统一显示。
基本绘图元素详解
Matplotlib 支持几乎所有常见的图表类型。
折线图 (plot)
import matplotlib.pyplot as plt
import numpy as np
# 准备数据
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
# 绘制
plt.plot(x, y)"A simple plot") # 添加标题
plt.xlabel("X-axis") # 添加 X 轴标签
plt.ylabel("Y-axis") # 添加 Y 轴标签
plt.show()
散点图 (scatter)
import matplotlib.pyplot as plt import numpy as np # 生成随机数据 np.random.seed(0) x = np.random.rand(50) y = np.random.rand(50) colors = np.random.rand(50) sizes = 1000 * np.random.rand(50) # 绘制散点图 plt.scatter(x, y, c=colors, s=sizes, alpha=0.5, cmap='viridis') plt.colorbar() # 显示颜色条"Scatter Plot") plt.show()
柱状图 (bar, barh)
import matplotlib.pyplot as plt
# 准备数据
categories = ['A', 'B', 'C', 'D']
values = [15, 30, 45, 10]
# 绘制垂直柱状图
plt.bar(categories, values, color=['red', 'blue', 'green', 'yellow'])"Vertical Bar Chart")
plt.ylabel("Value")
plt.show()
# 绘制水平柱状图
plt.barh(categories, values, color=['red', 'blue', 'green', 'yellow'])"Horizontal Bar Chart")
plt.xlabel("Value")
plt.show()
直方图 (hist)
直方图用于展示数据的分布情况。
import matplotlib.pyplot as plt
import numpy as np
# 生成正态分布数据
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
# 绘制直方图
plt.hist(x, bins=50, color='green', alpha=0.7) # bins 指的是柱子的数量"Histogram of IQ")
plt.xlabel("IQ")
plt.ylabel("Frequency")
plt.show()
饼图 (pie)
import matplotlib.pyplot as plt
# 准备数据
labels = 'Python', 'Java', 'C++', 'JavaScript'
sizes = [35, 30, 20, 15]
explode = (0.1, 0, 0, 0) # 突出显示第一个扇形
# 绘制饼图
plt.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True, startangle=90)
plt.axis('equal') # 保证饼图是圆的"Programming Language Popularity")
plt.show()
箱线图 (boxplot)
箱线图是展示数据分布的另一种方式,可以显示中位数、四分位数和异常值。
import matplotlib.pyplot as plt
import numpy as np
# 生成多组数据
data = [np.random.normal(0, std, 100) for std in range(1, 4)]
# 绘制箱线图
plt.boxplot(data, patch_artist=True)
plt.xticks([1, 2, 3], ['Group 1', 'Group 2', 'Group 3'])"Boxplot Example")
plt.ylabel("Value")
plt.show()
图表个性化:让图表更专业
通过修改各种参数,你可以让图表信息更丰富、更美观。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
# 创建图形和坐标轴
fig, ax = plt.subplots(figsize=(10, 6)) # 创建一个 10x6 英寸的画布
# 绘制两条线
ax.plot(x, y1, label='sin(x)', color='blue', linestyle='--', linewidth=2)
ax.plot(x, y2, label='cos(x)', color='red', marker='o', markersize=4, linestyle='-.') # 标记点
和标签
ax.set_title('Sine and Cosine Waves', fontsize=16, pad=20)
ax.set_xlabel('X-axis (radians)', fontsize=12)
ax.set_ylabel('Y-axis', fontsize=12)
# 设置图例
ax.legend(loc='upper right', fontsize=10) # loc 可以是 'upper left', 'lower right' 等
# 设置坐标轴范围
ax.set_xlim([0, 10])
ax.set_ylim([-1.2, 1.2])
# 设置刻度
ax.set_xticks(np.arange(0, 11, 2)) # 从 0 到 10,每隔 2 一个刻度
ax.set_yticks([-1, 0, 1])
# 添加网格
ax.grid(True, linestyle=':', color='gray', alpha=0.6)
# 显示
plt.show()
个性化参数总结:
figsize=(width, height): 设置画布大小。label: 为数据系列命名,用于图例。color: 设置颜色 (如'red','#FF5733')。linestyle: 线条样式 (, , , )。linewidth: 线条宽度。marker: 标记点样式 ('o','s','^', )。markersize: 标记点大小。set_title(): 设置标题。set_xlabel(),set_ylabel(): 设置坐标轴标签。legend(): 显示图例。set_xlim(),set_ylim(): 设置坐标轴范围。set_xticks(),set_yticks(): 设置刻度位置。grid(): 显示/隐藏网格。
保存图片 (savefig)
使用 savefig 可以将图表保存为图片文件,支持多种格式(如 PNG, JPG, PDF, SVG)。
# ... (使用上面的绘图代码)
# 在 plt.show() 之前调用
fig.savefig('my_figure.png', dpi=300, bbox_inches='tight')
fig.savefig('my_figure.pdf', format='pdf')
dpi: 分辨率,越高图片越清晰。bbox_inches='tight': 自动裁剪掉图表周围多余的空白。
进阶:多图与子图布局
你可以在一个画布上绘制多个图表,这就是子图。
plt.subplot():简单网格布局
plt.subplot(nrows, ncols, index) 创建一个子网格。
nrows: 行数ncols: 列数index: 当前子图的索引(从 1 开始,从左到右,从上到下)
import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) # 创建一个 2x2 的子图网格 plt.subplot(2, 2, 1) # 第1个子图 plt.plot(x, np.sin(x))'Sin(x)') plt.subplot(2, 2, 2) # 第2个子图 plt.plot(x, np.cos(x))'Cos(x)') plt.subplot(2, 2, 3) # 第3个子图 plt.plot(x, np.tan(x))'Tan(x)') plt.subplot(2, 2, 4) # 第4个子图 plt.plot(x, x**2)'x^2') plt.tight_layout() # 自动调整子图间距,防止重叠 plt.show()
plt.subplots():创建整个 Figure 和 Axes
这是更现代、更推荐的方法,特别是当你需要操作多个子图时,它会返回一个包含 Figure 和 Axes 对象的元组。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
# 创建一个 2x2 的网格,并获取所有 Axes 对象
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
# axes 是一个二维数组,可以通过 axes[row, col] 来访问每个子图
axes[0, 0].plot(x, np.sin(x))
axes[0, 0].set_title('Sin(x)')
axes[0, 1].plot(x, np.cos(x))
axes[0, 1].set_title('Cos(x)')
axes[1, 0].plot(x, np.tan(x))
axes[1, 0].set_title('Tan(x)')
axes[1, 0].set_ylim([-1, 1]) # 单独设置某个子图的坐标轴范围
axes[1, 1].plot(x, x**2)
axes[1, 1].set_title('x^2')
# 使用 tight_layout 调整布局
fig.tight_layout()
plt.show()
GridSpec:更灵活的复杂布局
当你需要创建非均匀大小的子图时,GridSpec 是最佳选择。
import matplotlib.pyplot as plt
import numpy as np
# 创建一个 GridSpec 对象,定义 3 行 3 列的网格
gs = plt.GridSpec(3, 3, hspace=0.3, wspace=0.3)
fig = plt.figure(figsize=(8, 8))
# 创建第一个子图,占据第 0 行的所有列
ax1 = fig.add_subplot(gs[0, :])
ax1.plot(np.random.rand(10))
ax1.set_title('First Plot (spans all columns)')
# 创建第二个子图,占据第 1 行的前两列
ax2 = fig.add_subplot(gs[1, :2])
ax2.plot(np.random.rand(10))
ax2.set_title('Second Plot (spans two columns)')
# 创建第三个子图,占据第 1 行的第 3 列
ax3 = fig.add_subplot(gs[1, 2])
ax3.plot(np.random.rand(10))
ax3.set_title('Third Plot')
# 创建第四个子图,占据第 2 行的所有列
ax4 = fig.add_subplot(gs[2, :])
ax4.plot(np.random.rand(10))
ax4.set_title('Fourth Plot (spans all columns)')
plt.show()
高级主题:文本、注释与样式
添加文本 (text, annotate)
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(0, 20, 1000)
ax.plot(x, np.cos(x))
# 在特定坐标点添加文本
ax.text(10, 0, 'Maximum Point', fontsize=12, ha='center') # ha 是水平对齐方式
# 添加带箭头的注释
ax.annotate('Local Minimum',
xy=(5 * np.pi, -1), # 箭头尖头的位置
xytext=(10, 0), # 文本的位置
arrowprops=dict(facecolor='black', shrink=0.05),
fontsize=12)
ax.set_title('Text and Annotation Example')
plt.show()
使用样式表 (plt.style.use)
Matplotlib 内置了多种预设的样式,可以快速改变图表的整体外观。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
# 尝试不同的样式
styles = ['seaborn-v0_8-whitegrid', 'ggplot', 'dark_background', 'classic']
for style in styles:
plt.style.use(style)
fig, ax = plt.subplots()
ax.plot(x, y, label=f'Sin(x) in {style}')
ax.legend()
plt.title(f'Style: {style}')
plt.show() # 每次显示一个
配置参数 (rcParams)
如果你想更深入地定制 Matplotlib 的默认行为,可以修改 rcParams 字典。
import matplotlib.pyplot as plt
import numpy as np
# 修改全局默认字体和大小
plt.rcParams.update({
'font.size': 12,
'font.family': 'serif',
'axes.labelsize': 14,
'axes.titlesize': 16,
'xtick.labelsize': 10,
'ytick.labelsize': 10,
})
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))"Global rcParams Example")
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
plt.show()
总结与最佳实践
- 从
plt.plot()开始:对于简单的探索性数据分析,pyplotAPI 快速且方便。 - 转向面向对象 API:对于更复杂的图表、多子图或需要精细控制的场景,强烈推荐使用
fig, ax = plt.subplots()的方式,它更清晰、更不易出错。 - 清晰的命名:为变量、坐标轴和标题使用描述性的名称。
- 不要忘记标签:一个没有标题和坐标轴标签的图表是没有意义的。
- 选择合适的图表类型:根据你的数据类型和分析目的选择最合适的可视化方式。
- 保持简洁:避免在图表上添加过多的装饰元素,以免喧宾夺主,网格、图例等应该服务于数据展示。
- 善用文档和示例:Matplotlib 官方文档 是最好的学习资源,里面有详细的 API 说明和海量的示例代码。
这份教程涵盖了 Matplotlib 的核心知识点,通过不断练习和尝试,你将能够利用它创造出既美观又信息丰富的数据可视化作品,祝你学习愉快!
