一文了解 Matplotlib:功能与使用基础 – wiki基地


一文了解 Matplotlib:功能与使用基础

数据是现代世界的基石,而数据可视化则是解读数据、发现洞察、进行有效沟通的关键工具。在 Python 的数据科学生态系统中,Matplotlib 无疑是最核心、最基础、也是最强大的数据可视化库之一。无论你是数据分析新手,还是经验丰富的数据科学家,掌握 Matplotlib 都是必不可少的技能。

本文将带你深入了解 Matplotlib 的核心功能,从最基本的概念到常用的图表类型和定制方法,帮助你建立坚实的使用基础。

1. 为什么选择 Matplotlib?

在 Python 中有许多优秀的可视化库,如 Seaborn、Plotly、Bokeh 等。它们各自有其特点和优势。那么,为什么我们还要学习 Matplotlib 呢?

  • 基石地位: Matplotlib 是许多其他高级可视化库(如 Seaborn)的底层依赖。理解 Matplotlib 的工作原理,能让你更好地使用这些库,并在需要时进行更精细的控制。
  • 强大与灵活: Matplotlib 提供了极其丰富的图表类型和几乎无限的定制选项。从简单的折线图到复杂的 3D 绘图,从调整线条粗细到精确定位图例和文本,Matplotlib 都能满足你的需求。
  • 控制力: Matplotlib 提供了两种主要的接口:Pyplot 接口和面向对象接口。面向对象接口允许你对图表的每一个元素进行精细控制,这在创建复杂或高度定制化的图表时尤为重要。
  • 成熟与稳定: Matplotlib 拥有悠久的历史和庞大的用户社区,这意味着它文档齐全、稳定可靠,遇到问题时很容易找到解决方案。
  • 与 NumPy/Pandas 完美集成: Matplotlib 与 Python 的数值计算库 NumPy 和数据处理库 Pandas 无缝集成,可以直接绘制 NumPy 数组或 Pandas DataFrames/Series 中的数据。

总而言之,Matplotlib 是 Python 数据可视化领域的“瑞士军刀”,它为你提供了创建几乎任何静态、交互式或动画图表的能力。

2. 安装 Matplotlib

安装 Matplotlib 非常简单,通常使用 pip 或 conda 包管理器。

使用 pip 安装:

bash
pip install matplotlib

如果你使用 Anaconda 发行版,Matplotlib 通常已经预装好了。如果没有,可以使用 conda 安装:

bash
conda install matplotlib

安装完成后,你就可以在 Python 脚本或 Jupyter Notebook 中导入它并开始使用了。最常用的导入方式是导入 pyplot 模块,并为其设置别名 plt

python
import matplotlib.pyplot as plt

3. Matplotlib 的“解剖学”:核心概念 (Figure 和 Axes)

理解 Matplotlib 的核心组件是掌握其使用的关键。最基本的两个组件是 FigureAxes

  • Figure (画布/窗口):
    Figure 是容纳所有图表元素的顶层容器。可以把它想象成一个空白的画布或者一个弹出式的图形窗口。一个 Figure 对象可以包含一个或多个 Axes 对象。它还包含 Figure 级别的元素,如图形标题 (suptitle)。

  • Axes (坐标系/绘图区域):
    Axes 是图表中实际绘制数据的区域。它是一个带有 x 轴、y 轴(对于 2D 图表)或 x、y、z 轴(对于 3D 图表)的坐标系。你可以把 Axes 想象成画布上的一个特定的绘图区域。大多数 Matplotlib 的绘图函数(如 plot(), scatter(), bar(), hist() 等)都属于 Axes 对象的方法。一个 Figure 可以有多个 Axes,这些 Axes 可以排列成子图(subplots)。

简而言之: Figure 是你作画的纸张或窗口,而 Axes 是你在纸张上画的各个独立的图(带坐标轴)。

理解 Pyplot 接口和面向对象接口:

Matplotlib 提供了两种主要的使用接口:

  1. Pyplot 接口 (plt): 这是一种基于状态的接口,模仿 MATLAB 的绘图方式。它会自动创建 Figure 和 Axes,并在当前活跃的 Axes 上进行绘图。对于快速创建简单图表非常方便。例如:
    python
    import matplotlib.pyplot as plt
    plt.plot([1, 2, 3], [4, 5, 6]) # Pyplot 自动创建 Figure 和 Axes 并绘图
    plt.xlabel('X轴')
    plt.ylabel('Y轴')
    plt.title('简单折线图')
    plt.show() # 显示 Figure

    虽然方便,但在处理多个子图或进行复杂定制时,Pyplot 接口有时会让人感到混乱,因为它隐藏了 Figure 和 Axes 对象的管理细节。

  2. 面向对象 (OO) 接口: 这是 Matplotlib 的核心。你显式地创建 FigureAxes 对象,然后调用 Axes 对象的方法来绘制数据和设置图表元素。这提供了对图表的完全控制。这是推荐的接口,特别是在创建复杂图表或需要在一个 Figure 中包含多个图表时。例如:
    “`python
    import matplotlib.pyplot as plt

    显式创建 Figure 和 Axes 对象

    fig, ax = plt.subplots() # 创建一个 Figure 和一个 Axes

    在 Axes 对象上绘图和设置属性

    ax.plot([1, 2, 3], [4, 5, 6])
    ax.set_xlabel(‘X轴’)
    ax.set_ylabel(‘Y轴’)
    ax.set_title(‘面向对象接口折线图’)

    plt.show() # 显示 Figure
    “`
    在本文后续的示例中,我们将尽量使用面向对象接口,因为它更能体现 Matplotlib 的结构,也更利于学习和掌握。

4. 基本图表类型及绘制

掌握了一些基础概念后,我们来看看如何使用 Matplotlib 绘制一些常见的图表。我们将使用 NumPy 生成一些示例数据。

“`python
import matplotlib.pyplot as plt
import numpy as np

为了中文显示正常

plt.rcParams[‘font.sans-serif’] = [‘SimHei’] # 指定默认字体
plt.rcParams[‘axes.unicode_minus’] = False # 解决保存图像时负号’-‘显示为方块的问题

生成示例数据

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
categories = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’]
values = np.random.rand(5) * 10
data_hist = np.random.randn(1000)
sizes = [15, 30, 45, 10]
labels = [‘类别1’, ‘类别2’, ‘类别3’, ‘类别4’]
“`

4.1 折线图 (Line Plot)

折线图常用于表示数据随时间或其他连续变量的变化趋势。

“`python

OO 接口绘制折线图

fig, ax = plt.subplots(figsize=(8, 4)) # 设置 Figure 大小

ax.plot(x, y1, label=’sin(x)’, color=’blue’, linestyle=’-‘) # 绘制第一条线
ax.plot(x, y2, label=’cos(x)’, color=’red’, linestyle=’–‘) # 绘制第二条线

ax.set_xlabel(‘X轴’)
ax.set_ylabel(‘Y轴’)
ax.set_title(‘正弦与余弦函数图’)
ax.legend() # 显示图例
ax.grid(True) # 添加网格线

plt.show()
``
*
plt.subplots(): 创建一个 Figure 和一个 Axes。
*
ax.plot(): 在 Axes 对象ax上绘制数据。可以传入x,y坐标。label用于图例,color设置颜色,linestyle设置线型。
*
ax.set_xlabel(),ax.set_ylabel(),ax.set_title(): 设置轴标签和标题。
*
ax.legend(): 显示图例,它会读取plot中设置的label
*
ax.grid(): 添加网格线。
*
plt.show()`: 显示图形窗口。

4.2 散点图 (Scatter Plot)

散点图用于展示两个数值变量之间的关系。

“`python

生成更多随机数据用于散点图

np.random.seed(42)
x_scatter = np.random.rand(50) * 10
y_scatter = np.random.rand(50) * 10
colors = np.random.rand(50) # 用颜色表示第三个维度
sizes_scatter = np.random.rand(50) * 200 # 用大小表示第四个维度

fig, ax = plt.subplots(figsize=(8, 6))

scatter = ax.scatter(x_scatter, y_scatter, c=colors, s=sizes_scatter, alpha=0.7, cmap=’viridis’)

c: 颜色数组, s: 大小数组, alpha: 透明度, cmap: 颜色映射

ax.set_xlabel(‘X轴’)
ax.set_ylabel(‘Y轴’)
ax.set_title(‘随机散点图 (颜色和大小表示额外维度)’)

添加颜色条 (可选,如果使用颜色映射)

fig.colorbar(scatter, label=’颜色维度’)

plt.show()
``
*
ax.scatter(): 绘制散点图。c参数可以是一个颜色列表,也可以是一个数值数组,此时需要通过cmap参数指定颜色映射。s参数控制点的大小。alpha控制透明度。
*
fig.colorbar()`: 为使用颜色映射的散点图添加颜色条,用于解释颜色对应的数值范围。

4.3 柱状图 (Bar Plot)

柱状图用于比较不同类别的数据。

“`python
fig, ax = plt.subplots(figsize=(8, 5))

bar_container = ax.bar(categories, values, color=[‘skyblue’, ‘lightcoral’, ‘lightgreen’, ‘gold’, ‘plum’])

ax.bar() 返回一个容器对象,可以用来进一步操作柱子

ax.set_xlabel(‘类别’)
ax.set_ylabel(‘值’)
ax.set_title(‘各类别值比较’)

ax.set_xticklabels(categories) # 也可以这样设置 x 轴标签

在柱子上方显示数值 (可选)

ax.bar_label(bar_container, fmt=’%.2f’) # 显示数值,格式化为小数点后两位

plt.show()
``
*
ax.bar(): 绘制垂直柱状图。第一个参数是类别标签(x 坐标),第二个参数是对应的高度(y 坐标)。color可以是一个颜色列表。
*
ax.bar_label()`: 一个方便的函数,用于在每个柱子顶部添加文本标签,通常是柱子的高度值。

4.4 直方图 (Histogram)

直方图用于显示一组数据的分布情况。它将数据分成若干个“bin”(区间),然后计算每个 bin 中数据的数量。

“`python
fig, ax = plt.subplots(figsize=(8, 5))

ax.hist(data_hist, bins=30, color=’teal’, edgecolor=’black’, alpha=0.7)

bins: 区间的数量或边界, edgecolor: 柱子边缘颜色, alpha: 透明度

ax.set_xlabel(‘值’)
ax.set_ylabel(‘频数’)
ax.set_title(‘随机数据直方图’)

plt.show()
``
*
ax.hist(): 绘制直方图。第一个参数是数据数组,bins` 参数是关键,它决定了分组的方式。

4.5 饼图 (Pie Chart)

饼图用于显示各部分在整体中所占的比例。

“`python
fig, ax = plt.subplots(figsize=(6, 6)) # 饼图通常需要等比例的 Figure 大小

explode = (0, 0.1, 0, 0) # 突出显示第二个类别 (可选)

ax.pie(sizes, explode=explode, labels=labels, autopct=’%1.1f%%’, shadow=True, startangle=90)

explode: 突出显示设置, labels: 标签, autopct: 显示比例的格式, shadow: 阴影, startangle: 起始角度

ax.set_title(‘各类别比例’)
ax.axis(‘equal’) # 保证饼图是圆的

plt.show()
``
*
ax.pie(): 绘制饼图。sizes是每个部分的数值,labels是对应的标签。autopct参数用于设置百分比文本的格式。explode参数可以让某些扇形突出显示。
*
ax.axis(‘equal’)`: 确保 x 和 y 轴的比例相等,使得饼图显示为圆形而不是椭圆。

注意: 饼图在分类过多或各部分比例相似时,不易于解读,应谨慎使用。

5. 图表元素的定制与美化

Matplotlib 提供了丰富的选项来定制图表的每一个细节,使其更具可读性和吸引力。

5.1 设置标题和轴标签

前面已经看到过,使用 ax.set_title(), ax.set_xlabel(), ax.set_ylabel() 方法。

python
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [1, 4, 9])
ax.set_title('平方函数', fontsize=16, color='darkblue') # 可以设置字体大小和颜色
ax.set_xlabel('输入值', fontsize=12)
ax.set_ylabel('平方值', fontsize=12)
plt.show()

5.2 设置轴的范围和刻度

使用 ax.set_xlim(), ax.set_ylim() 设置轴的显示范围。
使用 ax.set_xticks(), ax.set_yticks() 设置刻度的位置。
使用 ax.set_xticklabels(), ax.set_yticklabels() 设置刻度的文本标签。

“`python
fig, ax = plt.subplots()
ax.plot(x, y1)

ax.set_xlim(0, 5) # 只显示 x 从 0 到 5 的部分
ax.set_ylim(-1.2, 1.2) # 设置 y 轴范围

设置 x 轴特定刻度

ax.set_xticks([0, np.pi/2, np.pi, 3np.pi/2, 2np.pi])

设置 x 轴刻度对应的文本标签 (使用 LaTeX 格式表示数学符号)

ax.set_xticklabels([‘0′, r’$\pi/2$’, r’$\pi$’, r’$3\pi/2$’, r’$2\pi$’])

plt.show()
``
*
r’$\pi$’: 在 Matplotlib 中,可以在字符串前加上r并使用$` 符号将文本格式化为 LaTeX 表达式,用于显示数学符号。

5.3 自定义线条和标记

ax.plot()ax.scatter() 方法中,可以使用参数控制外观:
* color: 线条或标记的颜色 (如 'red', 'blue', '#FF5733')
* linestyle: 线型 (如 '-' 实线, '--' 虚线, '-.' 点划线, ':' 点线)
* linewidth: 线条宽度
* marker: 标记样式 (如 'o' 圆点, 'x' 叉, '*' 星号, 's' 正方形)
* markersize: 标记大小
* alpha: 透明度 (0.0 完全透明 到 1.0 完全不透明)

python
fig, ax = plt.subplots()
ax.plot(x[::10], y1[::10], color='purple', linestyle='-.', linewidth=2,
marker='o', markersize=8, label='带有标记的曲线')
ax.legend()
plt.show()

* [::10]: 使用切片每隔 10 个点取一个,用于减少标记的数量,使图表更清晰。

5.4 添加文本和注释

可以使用 ax.text() 在图表中的任意位置添加文本,使用 ax.annotate() 添加带箭头的注释。

“`python
fig, ax = plt.subplots()
ax.plot(x, y1)
ax.set_ylim(-1.2, 1.2)

添加文本

ax.text(5, 1, ‘这是峰值附近’, fontsize=10, color=’green’)

添加注释 (指向特定点)

peak_x = np.pi/2
peak_y = np.sin(peak_x)
ax.annotate(‘局部最高点’, # 注释文本
xy=(peak_x, peak_y), # 被注释点的坐标
xytext=(peak_x + 1, peak_y + 0.5), # 注释文本的坐标
arrowprops=dict(facecolor=’black’, shrink=0.05)) # 箭头样式

plt.show()
``
*
ax.annotate():xy参数是被注释点的位置,xytext是注释文本的位置。arrowprops` 是一个字典,用于定义箭头的样式。

5.5 添加图例 (Legend)

前面已经用过了 ax.legend()。确保在绘制每条线或散点系列时设置了 label 参数。ax.legend() 还有很多参数可以控制图例的位置、列数、边框等。

“`python
fig, ax = plt.subplots()
ax.plot(x, y1, label=’Sine’)
ax.plot(x, y2, label=’Cosine’)

自定义图例位置和样式

ax.legend(loc=’upper right’, # 位置,如 ‘upper left’, ‘lower right’, ‘best’ (自动选择最佳位置)
ncol=1, # 列数
fancybox=True, # 圆角边框
shadow=True, # 阴影
fontsize=’small’) # 字体大小

plt.show()
“`

6. 子图 (Subplots)

在一个 Figure 中创建多个 Axes(即子图)是非常常见的需求,用于比较不同数据集或展示同一数据从不同角度的视图。

前面介绍 OO 接口时,我们使用了 plt.subplots()。这是创建子图最推荐的方式。

plt.subplots(nrows=1, ncols=1, ..., sharex=False, sharey=False):
* nrows: 子图的行数。
* ncols: 子图的列数。
* 返回值:一个 Figure 对象和一个 AxesAxes 对象的 NumPy 数组。
* 如果 nrows=1ncols=1 (默认),ax 返回一个 Axes 对象。
* 如果 nrows > 1ncols > 1ax 返回一个 NumPy 数组,其中包含所有 Axes 对象。你需要使用索引(如 ax[0, 0], ax[1]) 来访问每个子图。

6.1 创建 2×2 的子图

“`python
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))

axes 是一个 2×2 的 NumPy 数组

访问每个子图:axes[行索引, 列索引]

左上角子图 (axes[0, 0])

axes[0, 0].plot(x, y1)
axes[0, 0].set_title(‘Sin(x)’)

右上角子图 (axes[0, 1])

axes[0, 1].plot(x, y2, color=’orange’)
axes[0, 1].set_title(‘Cos(x)’)

左下角子图 (axes[1, 0])

axes[1, 0].scatter(x_scatter[:20], y_scatter[:20]) # 只取前20个点
axes[1, 0].set_title(‘部分散点图’)

右下角子图 (axes[1, 1])

axes[1, 1].hist(data_hist[::50], bins=10, color=’green’) # 只取部分数据,少些 bins
axes[1, 1].set_title(‘部分直方图’)

调整子图之间的间距,防止重叠

fig.tight_layout()

plt.show()
``
*
fig, axes = plt.subplots(2, 2, …)返回一个 Figure 对象fig和一个 2x2 的 Axes 对象数组axes
* 我们通过
axes[0, 0],axes[0, 1],axes[1, 0],axes[1, 1]分别访问并绘制在不同的子图上。
*
fig.tight_layout()` 尝试自动调整子图参数,以使它们紧凑排列。

6.2 共享轴 (Sharing Axes)

有时你希望某些子图共享 x 轴或 y 轴,这在比较数据或节省空间时很有用。可以在 plt.subplots() 中使用 sharexsharey 参数。

“`python

共享 x 轴的两个子图

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(8, 6))

上面子图

axes[0].plot(x, y1, label=’Sin(x)’)
axes[0].set_title(‘共享 X 轴的两个图’)
axes[0].set_ylabel(‘值 1’)
axes[0].legend()
axes[0].grid(True) # 单独为这个子图添加网格

下面子图

axes[1].plot(x, y2, color=’orange’, label=’Cos(x)’)
axes[1].set_xlabel(‘X轴’) # x 轴标签只在最下面的子图显示
axes[1].set_ylabel(‘值 2’)
axes[1].legend()
axes[1].grid(True) # 单独为这个子图添加网格

fig.tight_layout() # 调整布局
plt.show()
``
*
sharex=True`: 所有子图共享 x 轴的范围和刻度。y 轴同理。

7. 保存图表

绘制好的图表通常需要保存到文件中。使用 Figure 对象的 savefig() 方法。

“`python
fig, ax = plt.subplots()
ax.plot(x, y1)
ax.set_title(‘要保存的图’)
ax.set_xlabel(‘X’)
ax.set_ylabel(‘Y’)

保存图表

fig.savefig(‘my_plot.png’) # 保存为 PNG 格式,默认分辨率

保存为其他格式,设置分辨率,去掉白边

fig.savefig(‘my_plot.pdf’, format=’pdf’, dpi=300, bbox_inches=’tight’)
fig.savefig(‘my_plot.svg’, format=’svg’) # 矢量图格式,放大不失真

plt.show() # 显示图表 (savefig 不会自动显示)
``
*
fig.savefig(filename, format=None, dpi=None, bbox_inches=None, …):
*
filename: 保存的文件名 (后缀决定格式,也可以通过format指定)。
*
format: 文件格式,如‘png’,‘pdf’,‘svg’,‘jpg’,‘eps’等。
*
dpi: 分辨率 (每英寸点数),提高 DPI 可以获得更清晰的图像,特别适用于打印。矢量图 (如 pdf, svg) 不受 DPI 影响。
*
bbox_inches=’tight’`: 尝试去除图表周围多余的空白区域。

8. 进一步探索 (Beyond Basics)

Matplotlib 的功能远不止这些基础内容。一旦掌握了核心概念和基本用法,你可以进一步探索:

  • 图表样式 (Styles): Matplotlib 提供了一些预设的图表样式,可以快速改变图表的整体外观,例如 plt.style.use('ggplot')plt.style.use('seaborn-v0_8')
  • 文本和数学公式: 更高级的文本处理和完整的 LaTeX 支持。
  • 颜色映射 (Colormaps): 如何使用颜色梯度来表示数据,例如在热力图或散点图中。
  • 三维绘图 (3D Plotting): 使用 mpl_toolkits.mplot3d 工具包绘制三维图表。
  • 图像处理: Matplotlib 可以加载、显示和处理图像。
  • 动画 (Animation): 创建动态图表。
  • 嵌入到 GUI 应用: 将 Matplotlib 图表嵌入到 PyQt, Tkinter 或 wxPython 等图形用户界面应用中。
  • 自定义对象: 创建自定义的 Axes、Artist 等,实现更高级的定制。

9. 总结

Matplotlib 是 Python 数据可视化领域的基石。掌握它的核心概念——Figure(画布)和 Axes(坐标系/绘图区域),以及面向对象的接口,将为你打开数据可视化的大门。

本文详细介绍了:
* Matplotlib 的重要性。
* 安装方法。
* 核心组件 FigureAxes 的区别与联系,以及 Pyplot 接口和面向对象接口。
* 如何绘制常见的图表类型:折线图、散点图、柱状图、直方图、饼图,并使用了面向对象接口进行演示。
* 图表元素的定制与美化方法,包括标题、标签、轴范围、刻度、线条样式、标记、文本注释和图例。
* 如何在 Figure 中创建多个子图,并进行布局调整和轴共享。
* 如何将绘制好的图表保存到文件。

虽然 Matplotlib 的参数众多,可能初学时会感到有些复杂,但其逻辑是清晰的。通过理解 Figure 和 Axes 的层级关系,以及大多数定制选项都作为 Axes 对象的方法来调用,你就能更好地组织代码和控制图表。

最好的学习方法是实践。尝试用 Matplotlib 绘制你自己的数据,不断查阅官方文档(非常详细且有大量示例),你会发现它强大的功能和无限的可能性。

希望通过本文,你对 Matplotlib 的功能和基础使用有了全面而深入的了解,并能充满信心地开启你的 Python 数据可视化之旅!祝你学习愉快,绘图顺利!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部