Matplotlib 入门教程:数据可视化的第一步
数据是现代科学和商业的基石,而将数据转化为易于理解的图形是数据分析中不可或缺的一步。数据可视化能够帮助我们发现数据中的模式、趋势、异常点,并有效地传达分析结果。在 Python 领域,Matplotlib 是最流行、最基础的数据可视化库之一,它功能强大且灵活,能够创建从简单的折线图到复杂的 3D 图形的各种图表。
本篇文章将带你从零开始,详细学习 Matplotlib 的基本使用方法,掌握如何绘制常见图表、进行图表定制,并理解 Matplotlib 的核心概念。无论你是数据科学新手,还是希望系统学习 Matplotlib,本文都将为你打下坚实的基础。
本文内容概要:
- 什么是 Matplotlib?
- 安装 Matplotlib
- Matplotlib 的两种接口:Pyplot 与面向对象接口
- 绘制第一个图表:简单的折线图 (使用 Pyplot)
- 理解 Matplotlib 的核心组件:Figure 和 Axes (引入面向对象接口)
- 使用面向对象接口绘制图表
- 图表基本定制:标题、轴标签、图例
- 控制线条样式与标记
- 设置轴范围与刻度
- 添加网格线
- 绘制不同类型的图表:
- 散点图 (Scatter Plot)
- 柱状图 (Bar Plot)
- 直方图 (Histogram)
- 创建多个子图 (Subplots)
- 保存图表
- Matplotlib 与其他库的协作 (NumPy 和 Pandas)
- 进阶方向与资源
1. 什么是 Matplotlib?
Matplotlib 是一个用于创建静态、动态、交互式图表的 Python 库。它最初设计用于模仿 MATLAB 的绘图功能,因此语法风格在某些方面与 MATLAB 相似。Matplotlib 功能丰富,支持多种操作系统上的各种后端,可以将图表输出为多种硬拷贝格式和交互式环境。
为什么选择 Matplotlib?
* 强大灵活: 几乎可以定制图表的每一个方面。
* 历史悠久: 社区庞大,资源丰富,遇到问题容易找到解决方案。
* 基础库: 许多其他高级可视化库 (如 Seaborn、Pandas 的绘图功能) 都构建在 Matplotlib 之上,掌握 Matplotlib 是学习这些库的基础。
* 集成良好: 与 NumPy、Pandas 等科学计算库无缝集成。
2. 安装 Matplotlib
安装 Matplotlib 非常简单,使用 Python 的包管理器 pip 即可。如果你已经安装了 Python 和 pip,只需要在终端或命令行执行以下命令:
bash
pip install matplotlib
如果你还想使用一些更高级的功能,或者需要特定的字体、后端,可能还需要安装一些依赖库。但对于入门来说,上面的命令通常就足够了。建议在一个虚拟环境中安装库,以避免版本冲突。
安装完成后,你可以在 Python 环境中导入它来验证安装是否成功:
python
import matplotlib.pyplot as plt
print("Matplotlib 安装成功!")
如果没有报错并输出了信息,说明安装成功。
3. Matplotlib 的两种接口:Pyplot 与面向对象接口
Matplotlib 提供了两种主要的绘图接口:
- Pyplot 接口 (pyplot API): 这是 Matplotlib 最早、最简单易用的接口,它模仿了 MATLAB 的绘图语法。通过
matplotlib.pyplot
模块(通常导入为plt
)提供一系列函数,如plt.plot()
,plt.xlabel()
,plt.title()
等。这些函数会自动创建 Figure 和 Axes 对象并在当前 Axes 上进行操作。对于简单快速的绘图任务,Pyplot 接口非常方便。 - 面向对象接口 (Object-Oriented API): 这是 Matplotlib 更推荐的接口,尤其是在创建复杂图表或需要精细控制图表元素时。通过这个接口,你需要显式地创建 Figure 和 Axes 对象,然后调用 Axes 对象的方法(如
ax.plot()
,ax.set_xlabel()
,ax.set_title()
)来绘制和定制图表。这种方式更加清晰、可控,尤其是在处理多个子图时。
在本文中,我们将先从 Pyplot 接口入门,然后快速过渡到面向对象接口,因为后者在实际开发中更常用且更强大。
4. 绘制第一个图表:简单的折线图 (使用 Pyplot)
我们先用 Pyplot 接口来绘制一个简单的折线图。
“`python
导入 matplotlib.pyplot 模块,通常简写为 plt
import matplotlib.pyplot as plt
导入 numpy 库用于生成数据
import numpy as np
生成一些示例数据
创建一个包含从 0 到 10 的 100 个点的数组作为 x 轴数据
x = np.linspace(0, 10, 100)
计算 x 对应的 sin(x) 值作为 y 轴数据
y = np.sin(x)
使用 plt.plot() 函数绘制折线图
plt.plot() 会自动创建一个 Figure 和一个 Axes,并在当前 Axes 上绘制数据
plt.plot(x, y)
使用 plt.title() 设置图表标题
plt.title(“Simple Sine Wave”)
使用 plt.xlabel() 设置 x 轴标签
plt.xlabel(“x value”)
使用 plt.ylabel() 设置 y 轴标签
plt.ylabel(“sin(x)”)
使用 plt.grid() 添加网格线
plt.grid(True)
使用 plt.show() 显示图表
在 Jupyter Notebook 或 IPython 环境中,通常不需要这一行,图表会自动显示
在脚本中运行,这一行是必需的
plt.show()
“`
代码解释:
import matplotlib.pyplot as plt
: 导入pyplot
模块并约定俗成地命名为plt
。import numpy as np
: 导入numpy
库,用于方便地生成数值数据。x = np.linspace(0, 10, 100)
: 使用numpy.linspace
函数生成一个包含 100 个点的等间距数组,范围从 0 到 10。y = np.sin(x)
: 计算x
数组中每个元素的正弦值,得到y
数组。plt.plot(x, y)
: 这是核心绘图命令。它接收 x 和 y 坐标作为输入,并绘制一条连接这些点的线。如果只提供一个数组,plt.plot()
会将其作为 y 值,并自动生成从 0 到 N-1(N 是数组长度)的整数作为 x 值。plt.title()
,plt.xlabel()
,plt.ylabel()
: 这些函数用于添加图表标题和轴标签,增强图表的可读性。plt.grid(True)
: 添加网格线,帮助读取图上的数据点。plt.show()
: 显示绘制的图表窗口。如果在交互式环境(如 Jupyter Notebook)中,通常不用显式调用此函数,图表会在代码块执行后自动显示。但在 Python 脚本中运行,必须调用此函数才能看到图表。
运行这段代码,你应该会看到一个带有标题、轴标签和网格线的正弦波折线图窗口。
5. 理解 Matplotlib 的核心组件:Figure 和 Axes
在使用 Pyplot 接口时,Matplotlib 默默地为我们创建了图表对象。为了更好地控制图表,我们需要理解 Matplotlib 的两个核心概念:
- Figure (图表): Figure 是最顶层的容器,可以理解为一个空白的画布或窗口。所有的图表元素(Axes、标题、图例等)都位于 Figure 中。一个 Figure 可以包含一个或多个 Axes。你可以通过
plt.figure()
创建一个 Figure 对象。 - Axes (坐标系): Axes 是我们实际绘制数据的地方。它包含 x 轴、y 轴、刻度、标签、绘图区域等等。Axes 是 Figure 的子对象。一个 Figure 可以有多个 Axes,每个 Axes 都是一个独立的绘图区域。不要将 Axes 与 “轴” (Axis,指 x 轴或 y 轴) 混淆。
plt.plot()
等函数实际上是在当前的 Axes 上进行绘制。
Pyplot 接口的函数 (plt.plot()
, plt.xlabel()
, 等) 是面向“当前 Axes”操作的全局函数。这意味着它们作用于当前活动的 Figure 和 Axes。这种方式简单但对于多子图或复杂布局不太灵活。
面向对象接口则让你显式地创建 Figure 和 Axes 对象,然后直接调用 Axes 对象的方法进行绘制和定制。这是更推荐的方式,因为它提供了更细粒度的控制。
创建 Figure 和 Axes 的常用方法是使用 plt.subplots()
函数。
“`python
import matplotlib.pyplot as plt
创建一个 Figure 对象和一个 Axes 对象
fig 是 Figure 对象,ax 是 Axes 对象
默认创建一个 Figure,并在其中创建一个 1×1 的 Axes
fig, ax = plt.subplots()
现在我们可以使用 ax 对象的方法来绘制和定制图表
例如,使用 ax.plot() 而不是 plt.plot()
ax.set_title() 而不是 plt.title() 等等
print(type(fig)) # 输出
print(type(ax)) # 输出
“`
plt.subplots()
函数返回一个 Figure 对象和一个或一个 Axes 对象的数组(取决于你指定的子图数量)。对于单个子图(默认情况),它返回一个 Figure 对象和一个 Axes 对象。
6. 使用面向对象接口绘制图表
现在我们用面向对象接口来重写第一个例子。
“`python
import matplotlib.pyplot as plt
import numpy as np
生成数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
使用面向对象接口创建 Figure 和 Axes
fig 是 Figure 对象,ax 是 Axes 对象
fig, ax = plt.subplots()
在 Axes 对象上绘制数据
ax.plot(x, y)
在 Axes 对象上设置标题和标签
ax.set_title(“Simple Sine Wave (OO Interface)”)
ax.set_xlabel(“x value”)
ax.set_ylabel(“sin(x)”)
在 Axes 对象上添加网格线
ax.grid(True)
显示图表 (plt.show() 作用于当前的 Figure)
plt.show()
“`
代码解释:
fig, ax = plt.subplots()
: 创建一个 Figurefig
和一个 Axesax
。ax.plot(x, y)
: 调用ax
对象的方法来绘制数据。ax.set_title()
,ax.set_xlabel()
,ax.set_ylabel()
: 调用ax
对象的方法来设置标题和轴标签。注意方法名变成了set_
开头。ax.grid(True)
: 调用ax
对象的方法添加网格线。plt.show()
: 虽然我们使用了面向对象接口进行绘制和定制,但最终显示图表依然依赖于 Matplotlib 的后端,通常通过plt.show()
来触发绘制和显示过程。
这个例子看起来和 Pyplot 版本很相似,但这种方式在需要处理多个子图或更复杂布局时会显示出其优势。
为什么推荐面向对象接口?
- 清晰: 每个绘图操作和定制都明确关联到特定的 Axes 对象,代码更易读、易维护。
- 灵活: 更容易控制图表中的各个元素,尤其是在处理多个子图时,可以独立地控制每个子图。
- 强大: 许多高级功能只能通过 Axes 对象的方法使用。
从现在开始,我们将主要使用面向对象接口进行示例。
7. 图表基本定制:标题、轴标签、图例
我们已经看到了如何设置标题和轴标签。现在我们来学习如何添加图例、多个数据集以及更详细地定制这些元素。
“`python
import matplotlib.pyplot as plt
import numpy as np
生成两组数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
创建 Figure 和 Axes
fig, ax = plt.subplots(figsize=(8, 4)) # 设置图表尺寸,宽度8英寸,高度4英寸
绘制两条线,并给每条线设置 label 参数
ax.plot(x, y1, label=’sin(x)’)
ax.plot(x, y2, label=’cos(x)’)
设置标题
ax.set_title(“Sine and Cosine Waves”, fontsize=14) # 可以设置字体大小
设置轴标签
ax.set_xlabel(“x”, fontsize=12)
ax.set_ylabel(“y”, fontsize=12)
添加图例
ax.legend() 会根据之前 plot 中设置的 label 参数自动生成图例
ax.legend(loc=’upper right’) # 可以指定图例位置,如 ‘upper left’, ‘lower right’, ‘best’ 等
添加网格线
ax.grid(True, linestyle=’–‘, alpha=0.6) # 可以设置网格线样式和透明度
显示图表
plt.show()
“`
代码解释:
fig, ax = plt.subplots(figsize=(8, 4))
: 创建图表和坐标系,并指定图表的尺寸为 8×4 英寸。ax.plot(x, y1, label='sin(x)')
: 绘制第一条线。关键是在plot
函数中加入了label
参数。ax.plot(x, y2, label='cos(x)')
: 绘制第二条线,同样加入label
参数。ax.set_title("...", fontsize=14)
: 设置标题,并通过fontsize
参数调整字体大小。类似的,set_xlabel
和set_ylabel
也支持fontsize
参数。ax.legend(loc='upper right')
: 添加图例。ax.legend()
会查找 Axes 中所有带有label
参数的艺术家对象(Artist,如 Line2D),并将它们显示在图例中。loc
参数指定图例的位置。'best'
是默认值,Matplotlib 会尝试找到一个最佳位置以避免覆盖数据。ax.grid(True, linestyle='--', alpha=0.6)
: 添加网格线,并使用linestyle
设置为虚线,alpha
设置透明度。
运行这段代码,你会看到一个包含两条曲线、标题、轴标签和图例的图表。图例会帮助读者区分不同的曲线。
8. 控制线条样式与标记
plot()
函数可以接受许多参数来控制线条的外观。常用的参数包括:
color
: 线条颜色,可以使用颜色名称(如 ‘red’, ‘blue’)、缩写(如 ‘r’, ‘b’, ‘g’, ‘k’ 代表红、蓝、绿、黑)、十六进制颜色码(如 ‘#FF5733’)或 RGB 元组。linestyle
或ls
: 线条样式,如 ‘-‘, ‘–‘, ‘:’, ‘-.’, ” (无线条)。linewidth
或lw
: 线条宽度。marker
: 数据点的标记样式,如 ‘o’ (圆圈), ‘s’ (方形), ‘^’ (三角形), ‘*’ (星形), ‘.’ (点)。markersize
或ms
: 标记大小。markeredgecolor
或mec
: 标记边缘颜色。markerfacecolor
或mfc
: 标记填充颜色。alpha
: 透明度 (0.0 完全透明到 1.0 完全不透明)。
你也可以使用一个格式字符串来同时指定颜色、标记和线条样式,例如 'ro--'
表示红色圆圈标记的虚线。
“`python
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 50)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.sin(x) + np.cos(x)
fig, ax = plt.subplots(figsize=(10, 6))
定制线条样式和标记
ax.plot(x, y1, color=’blue’, linestyle=’-‘, linewidth=2, label=’sin(x)’) # 蓝色实线,线宽2
ax.plot(x, y2, color=’red’, linestyle=’–‘, marker=’o’, markersize=6, label=’cos(x)’) # 红色虚线,圆圈标记,标记大小6
ax.plot(x, y3, ‘g-.s’, markersize=8, label=’sin(x)+cos(x)’) # 绿色点划线,方形标记,使用格式字符串
ax.set_title(“Customized Line Styles”)
ax.set_xlabel(“x”)
ax.set_ylabel(“y”)
ax.legend()
ax.grid(True)
plt.show()
“`
这段代码展示了如何通过参数精细控制每条线的颜色、样式、宽度和标记。
9. 设置轴范围与刻度
控制轴的显示范围对于突出图表的特定区域或确保数据点完全可见非常重要。
ax.set_xlim(xmin, xmax)
: 设置 x 轴的显示范围。ax.set_ylim(ymin, ymax)
: 设置 y 轴的显示范围。
你也可以分别设置上下限,例如 ax.set_xlim(xmin=0)
只设置 x 轴的下限。
Matplotlib 会自动确定轴上的刻度位置,但有时你需要手动控制它们。
ax.set_xticks(ticks)
: 手动设置 x 轴的刻度位置(ticks
是一个数值列表或 NumPy 数组)。ax.set_yticks(ticks)
: 手动设置 y 轴的刻度位置。ax.set_xticklabels(labels)
: 手动设置 x 轴刻度对应的标签(labels
是一个字符串列表)。通常与set_xticks
结合使用。ax.set_yticklabels(labels)
: 手动设置 y 轴刻度对应的标签。
“`python
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(x, y)
ax.set_title(“Sine Wave with Custom Limits and Ticks”)
ax.set_xlabel(“x”)
ax.set_ylabel(“sin(x)”)
设置轴范围,例如只显示 sin(x) 在 0 到 pi*2 之间的部分
ax.set_xlim(0, 2 * np.pi)
ax.set_ylim(-1.2, 1.2) # 稍微超出数据范围,让曲线不贴边
设置 x 轴刻度为 pi 的倍数
创建刻度位置
x_ticks = np.arange(0, 2.1 * np.pi, np.pi / 2)
创建刻度标签
x_labels = [‘0′, r’$\pi/2$’, r’$\pi$’, r’$3\pi/2$’, r’$2\pi$’] # 使用 LaTeX 格式显示 π
ax.set_xticks(x_ticks)
ax.set_xticklabels(x_labels)
设置 y 轴刻度
y_ticks = [-1, 0, 1]
y_labels = [‘Min’, ‘Zero’, ‘Max’]
ax.set_yticks(y_ticks)
ax.set_yticklabels(y_labels)
ax.grid(True)
plt.show()
“`
这个例子展示了如何精确控制图表的显示范围和轴上的刻度及其标签。注意在标签中使用 r'$...$'
可以解析 LaTeX 格式的数学表达式。
10. 添加网格线
前面已经简单展示了如何添加网格线:ax.grid(True)
。你可以进一步定制网格线的样式。
ax.grid(True)
: 显示网格线。ax.grid(False)
: 隐藏网格线。ax.grid(axis='x')
: 只显示垂直网格线 (x 轴)。ax.grid(axis='y')
: 只显示水平网格线 (y 轴)。ax.grid(color='gray', linestyle='--', linewidth=0.5, alpha=0.5)
: 设置网格线的颜色、样式、线宽和透明度。
这部分内容在前面的例子中已经有所体现,不再单独提供长代码。
11. 绘制不同类型的图表
Matplotlib 支持多种标准图表类型。使用面向对象接口,这些通常是 Axes 对象的方法。
散点图 (Scatter Plot)
散点图用于显示两个数值变量之间的关系。
“`python
import matplotlib.pyplot as plt
import numpy as np
生成一些随机数据
np.random.seed(0) # 设置随机种子以便结果可重现
x = np.random.rand(50) * 10
y = np.random.rand(50) * 10
sizes = np.random.rand(50) * 1000 # 每个点的大小
colors = np.random.rand(50) # 每个点的颜色 (使用颜色映射)
fig, ax = plt.subplots(figsize=(8, 6))
绘制散点图
s 参数控制点的大小,c 参数控制点的颜色
scatter = ax.scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’viridis’)
ax.set_title(“Scatter Plot”)
ax.set_xlabel(“X Value”)
ax.set_ylabel(“Y Value”)
添加颜色条 (Colorbar) 来解释颜色映射
fig.colorbar(scatter, label=’Color Value’)
ax.grid(True)
plt.show()
“`
代码解释:
ax.scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap='viridis')
:scatter
方法用于绘制散点图。x
和y
是点的坐标。s
可以是一个单一数值(所有点大小相同)或一个与x
,y
长度相同的数组(每个点大小不同)。c
可以是一个单一颜色、一个颜色序列或一个数值序列(使用颜色映射 cmap)。alpha
控制点的透明度。cmap
指定颜色映射方案。fig.colorbar(scatter, label='Color Value')
: 如果散点图的颜色是基于数值的(使用c
和cmap
),通常需要添加一个颜色条来解释颜色与数值的对应关系。fig.colorbar()
需要一个可映射对象(如scatter
返回的对象)作为输入。
柱状图 (Bar Plot)
柱状图用于比较不同类别或组的数值。
“`python
import matplotlib.pyplot as plt
import numpy as np
类别标签
categories = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’]
每个类别的数值
values = np.array([25, 40, 30, 35, 20])
创建 Figure 和 Axes
fig, ax = plt.subplots(figsize=(8, 5))
绘制垂直柱状图
ax.bar(x_positions, heights)
x_positions 是柱子的 x 坐标,heights 是柱子的高度
x_pos = np.arange(len(categories)) # 生成 0, 1, 2, 3, 4 作为 x 坐标
ax.bar(x_pos, values, color=[‘blue’, ‘green’, ‘red’, ‘purple’, ‘orange’]) # 可以指定每个柱子的颜色
设置 x 轴刻度和标签
ax.set_xticks(x_pos) # 将刻度设置在每个柱子的中心
ax.set_xticklabels(categories) # 将刻度标签设置为类别名称
ax.set_title(“Bar Plot of Categories”)
ax.set_xlabel(“Category”)
ax.set_ylabel(“Value”)
添加数值标签到柱子上 (可选)
for i, v in enumerate(values):
ax.text(i, v + 1, str(v), ha=’center’, va=’bottom’) # ha=’center’ 水平居中,va=’bottom’ 垂直底部对齐
ax.grid(axis=’y’, linestyle=’–‘, alpha=0.6) # 只显示水平网格线
plt.show()
“`
代码解释:
ax.bar(x_pos, values, ...)
:bar
方法用于绘制垂直柱状图。第一个参数是柱子的 x 坐标,第二个参数是柱子的高度。x_pos
使用np.arange(len(categories))
生成,确保每个柱子在 x 轴上有独立的、等距的位置。ax.set_xticks(x_pos)
和ax.set_xticklabels(categories)
: 将 x 轴的刻度位置设置在柱子中心,并将刻度标签设置为对应的类别名称。ax.text(x, y, text, ...)
: 在指定的坐标 (x, y) 添加文本。这里用于在每个柱子上方显示其数值。
绘制水平柱状图可以使用 ax.barh()
方法,参数顺序变为 (y 坐标, 宽度)。
直方图 (Histogram)
直方图用于显示数值数据的分布情况。它将数据范围分割成一系列“箱子”(bins),然后统计落入每个箱子中的数据点的数量。
“`python
import matplotlib.pyplot as plt
import numpy as np
生成一些服从正态分布的随机数据
np.random.seed(1)
data = np.random.randn(1000) * 10 + 50 # 平均值 50,标准差 10
fig, ax = plt.subplots(figsize=(8, 5))
绘制直方图
bins 参数指定箱子的数量或箱子的边界
n_bins = 30 # 分成 30 个箱子
ax.hist(data, bins=n_bins, color=’skyblue’, edgecolor=’black’, alpha=0.7)
ax.set_title(“Histogram of Data Distribution”)
ax.set_xlabel(“Value”)
ax.set_ylabel(“Frequency”)
ax.grid(axis=’y’, linestyle=’–‘, alpha=0.6) # 只显示水平网格线
plt.show()
“`
代码解释:
ax.hist(data, bins=n_bins, ...)
:hist
方法用于绘制直方图。第一个参数是要绘制的数据。bins
参数非常重要,它可以是一个整数(指定箱子数量)或一个序列(指定箱子的边界)。color
设置柱子的颜色,edgecolor
设置柱子边缘的颜色,alpha
设置透明度。
12. 创建多个子图 (Subplots)
前面我们使用 plt.subplots()
创建了一个 Figure 包含一个 Axes。plt.subplots()
真正的强大之处在于它可以轻松创建包含多个 Axes 的 Figure,即子图。
plt.subplots(nrows, ncols)
函数可以创建 nrows
行、ncols
列的子图网格。它返回一个 Figure 对象和一个 Axes 对象数组(如果 nrows * ncols > 1
)或单个 Axes 对象(如果 nrows * ncols == 1
)。
“`python
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.sin(x * 2)
y4 = np.cos(x * 2)
创建一个 2×2 的子图网格
fig 是 Figure 对象
axes 是一个 2×2 的 Axes 对象数组 (一个 NumPy 数组)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))
axes 是一个二维数组,可以通过索引访问每个 Axes 对象
axes[0, 0] 是左上角的 Axes
axes[0, 1] 是右上角的 Axes
axes[1, 0] 是左下角的 Axes
axes[1, 1] 是右下角的 Axes
在左上角子图绘制 sin(x)
axes[0, 0].plot(x, y1, ‘b-‘)
axes[0, 0].set_title(“sin(x)”)
axes[0, 0].set_xlabel(“x”)
axes[0, 0].set_ylabel(“y”)
在右上角子图绘制 cos(x)
axes[0, 1].plot(x, y2, ‘r–‘)
axes[0, 1].set_title(“cos(x)”)
axes[0, 1].set_xlabel(“x”)
axes[0, 1].set_ylabel(“y”)
在左下角子图绘制 sin(2x)
axes[1, 0].plot(x, y3, ‘g-.’)
axes[1, 0].set_title(“sin(2x)”)
axes[1, 0].set_xlabel(“x”)
axes[1, 0].set_ylabel(“y”)
在右下角子图绘制 cos(2x)
axes[1, 1].plot(x, y4, ‘m:’)
axes[1, 1].set_title(“cos(2x)”)
axes[1, 1].set_xlabel(“x”)
axes[1, 1].set_ylabel(“y”)
调整子图之间的间距,避免标题和标签重叠
plt.tight_layout()
显示图表
plt.show()
“`
代码解释:
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))
: 创建一个 2 行 2 列共 4 个子图的 Figure。axes
现在是一个 NumPy 数组,形状是(2, 2)
。axes[i, j]
: 通过二维索引访问指定的子图 Axes 对象。- 在每个 Axes 对象上独立进行绘制和定制,就像处理单个 Axes 一样(使用
ax.plot()
,ax.set_title()
等方法)。 plt.tight_layout()
: 这个函数会自动调整子图参数,使之填充整个 Figure 区域,并尽量减少子图之间的重叠,强烈推荐在绘制多个子图后调用。
如果你创建单行或单列的子图,axes
返回的是一个一维数组。例如 plt.subplots(nrows=2, ncols=1)
会返回一个 Axes 数组 axes
,可以通过 axes[0]
和 axes[1]
来访问。
13. 保存图表
绘制好的图表可以通过 Figure 对象的 savefig()
方法保存到文件。
“`python
假设你已经通过前面的代码创建了 Figure 对象 fig
例如,从上面的子图例子中获取 fig 对象
保存图表为 PNG 文件
fig.savefig(“my_subplots.png”)
保存为其他格式,例如 PDF 或 SVG (矢量图)
fig.savefig(“my_subplots.pdf”)
fig.savefig(“my_subplots.svg”)
控制分辨率 (DPI – Dots Per Inch)
对于需要打印或高质量显示的图片,可以增加 DPI
fig.savefig(“my_subplots_high_res.png”, dpi=300)
控制保存时的边界,bbox_inches=’tight’ 尝试去除白边
fig.savefig(“my_subplots_tight.png”, bbox_inches=’tight’)
print(“图表已保存。”)
“`
fig.savefig()
方法非常方便,它可以根据文件名后缀自动识别保存格式。常用的格式有 .png
(位图,适合网页和屏幕显示)、.jpg
(位图,有损压缩)、.pdf
(矢量图,适合打印和嵌入文档)、.svg
(矢量图,适合网页和编辑)。
14. Matplotlib 与其他库的协作 (NumPy 和 Pandas)
Matplotlib 与 Python 的科学计算生态系统紧密集成。
- NumPy: NumPy 提供了高性能的多维数组对象,是 Matplotlib 数据输入的基础。我们前面的例子中大量使用了 NumPy 来生成数据。Matplotlib 函数直接接受 NumPy 数组作为输入。
- Pandas: Pandas 是一个强大的数据处理和分析库,提供了 DataFrame 和 Series 数据结构。Pandas 对象可以直接作为 Matplotlib 绘图函数的输入。实际上,Pandas 内置了基于 Matplotlib 的绘图功能,使用起来更方便,但理解 Matplotlib 基础对于定制 Pandas 生成的图表至关重要。
使用 Pandas DataFrame 绘图示例 (基于面向对象接口):
“`python
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
创建一个示例 DataFrame
data = {‘category’: [‘A’, ‘B’, ‘C’, ‘D’, ‘E’],
‘value1’: np.random.rand(5) * 50,
‘value2’: np.random.rand(5) * 30}
df = pd.DataFrame(data)
fig, ax = plt.subplots(figsize=(8, 5))
使用 DataFrame 的列直接绘图
ax.bar() 可以直接使用 DataFrame 列
df[‘category’] 作为 x 坐标 (Pandas 会处理类别数据)
df[‘value1’] 作为高度
bar1 = ax.bar(df[‘category’], df[‘value1′], label=’Value 1’, width=0.35)
绘制第二组柱子 (需要调整 x 坐标使其并排)
计算第二个柱子的 x 坐标,使其位于第一个柱子旁边
x_pos = np.arange(len(df[‘category’]))
bar2 = ax.bar(x_pos + 0.35, df[‘value2′], label=’Value 2′, width=0.35, color=’orange’)
设置 x 轴刻度和标签
ax.set_xticks(x_pos + 0.35 / 2) # 将刻度设置在两组柱子的中间
ax.set_xticklabels(df[‘category’])
ax.set_title(“Bar Plot from Pandas DataFrame”)
ax.set_xlabel(“Category”)
ax.set_ylabel(“Value”)
ax.legend()
ax.grid(axis=’y’, linestyle=’–‘, alpha=0.6)
plt.show()
“`
这个例子展示了 Matplotlib 如何轻松地接收 Pandas DataFrame 中的列作为绘图数据。虽然 Pandas 自身提供了更简单的绘图命令 (df.plot(kind='bar')
),但底层依然是 Matplotlib,因此理解 Matplotlib 的定制方法对于美化 Pandas 图表至关重要。
15. 进阶方向与资源
恭喜你,你已经掌握了 Matplotlib 的核心概念和基础用法!但这仅仅是 Matplotlib 功能的冰山一角。如果你想深入学习,可以探索以下方向:
- 更多图表类型: 饼图、箱线图、小提琴图、热力图、等高线图、3D 图、地图等。
- 高级定制: 添加注释 (annotations)、自定义刻度格式、修改字体、调整颜色映射 (colormaps)、创建双 Y 轴图表。
- 布局管理: 使用
GridSpec
或手动调整 Axes 位置来创建更复杂的子图布局。 - Styles: 使用
plt.style.use()
切换不同的图表风格,快速美化图表。 - 动画: 使用
matplotlib.animation
模块创建动态图表。 - 交互性: 在不同的后端 (如 Tkinter, Qt, WxWidgets) 中创建交互式图表。
- 与其他库结合: 深入学习 Pandas 的绘图功能,或者使用 Seaborn (基于 Matplotlib 的高级统计图库) 绘制更美观和复杂的统计图。
重要资源:
- Matplotlib 官方文档 (Official Documentation): 这是最权威、最全面的资源。特别是它的 Gallery,提供了各种图表的示例代码,是你学习高级技巧和图表类型的宝库。
- Matplotlib 教程 (Tutorials): 官方网站提供了详细的教程,包括对核心概念的深入解释。
- Stack Overflow: 遇到问题时,通常可以在 Stack Overflow 上找到解决方案。
结论
Matplotlib 是 Python 数据可视化的基石,掌握它为你打开了数据分析和科学探索的大门。从理解 Figure 和 Axes 的概念,到使用面向对象接口绘制和定制各种图表,你已经迈出了重要的一步。
数据可视化是一个实践性很强的技能,最好的学习方法是动手尝试。找一些数据集,尝试用 Matplotlib 绘制不同类型的图表,并不断尝试定制图表的外观,使其更清晰、更美观、更能有效地传达信息。
继续探索 Matplotlib 的强大功能,将你的数据故事用精彩的图表呈现出来吧!