第二章:Matplotlib 进阶绘图


文档摘要

第二章:Matplotlib 进阶绘图 第二章:Matplotlib 进阶绘图 在Matplotlib的世界中,基础绘图只是冰山一角。掌握了折线图、散点图和柱状图等基本图表之后,你会发现Matplotlib拥有更强大的功能,能够创建更复杂、更具表现力的数据可视化作品。本章将深入探讨Matplotlib的进阶绘图技巧,帮助你提升数据可视化的水平,让你的图表更专业、更具洞察力。 本章将涵盖以下主要内容: 更精细的图表定制: 超越默认设置,深入定制图表的各个方面,包括样式、颜色、文本、注解和图例,让图表更符合你的需求和审美。 多子图与复杂布局: 学习如何在同一画布上绘制多个子图,以及如何使用 等工具创建更复杂的图表布局,高效展示多维度数据。

第二章:Matplotlib 进阶绘图

第二章:Matplotlib 进阶绘图

在Matplotlib的世界中,基础绘图只是冰山一角。掌握了折线图、散点图和柱状图等基本图表之后,你会发现Matplotlib拥有更强大的功能,能够创建更复杂、更具表现力的数据可视化作品。本章将深入探讨Matplotlib的进阶绘图技巧,帮助你提升数据可视化的水平,让你的图表更专业、更具洞察力。

本章将涵盖以下主要内容:

  1. 更精细的图表定制: 超越默认设置,深入定制图表的各个方面,包括样式、颜色、文本、注解和图例,让图表更符合你的需求和审美。

  2. 多子图与复杂布局: 学习如何在同一画布上绘制多个子图,以及如何使用GridSpec等工具创建更复杂的图表布局,高效展示多维度数据。

  3. 三维绘图: 探索Matplotlib的三维绘图能力,创建散点图、曲面图和线框图等三维图表,展现数据的空间分布。

  4. 高级图表类型: 介绍一些超出常规图表类型的进阶图表,例如等高线图、热力图和流场图,用于可视化特定类型的数据和关系。

  5. 交互式绘图: 初步了解Matplotlib的交互式绘图功能,使用户能够与图表进行互动,探索数据细节。

  6. 性能优化技巧: 针对大数据量绘图,学习一些性能优化技巧,提升绘图效率。

通过本章的学习,你将能够充分利用Matplotlib的强大功能,绘制出更专业、更具洞察力、更令人印象深刻的数据可视化图表。

1. 更精细的图表定制

Matplotlib的默认设置虽然方便,但往往无法满足所有需求。为了创建更精美的图表,我们需要深入了解如何定制图表的各个元素。

1.1 样式(Styles):快速改变图表外观

Matplotlib提供了多种预定义的样式,可以一键改变图表的整体外观。使用样式可以快速统一图表风格,提升效率。

代码实践:

import matplotlib.pyplot as plt import numpy as np # 生成示例数据 x = np.linspace(0, 10, 100) y1 = np.sin(x) y2 = np.cos(x) # 使用不同的样式 plt.style.use('ggplot') # 使用 ggplot 样式 plt.plot(x, y1, label='sin(x)') plt.plot(x, y2, label='cos(x)') plt.title('使用 ggplot 样式') plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show() plt.style.use('seaborn-v0_8-darkgrid') # 使用 seaborn-darkgrid 样式 plt.plot(x, y1, label='sin(x)') plt.plot(x, y2, label='cos(x)') plt.title('使用 seaborn-darkgrid 样式') plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show() plt.style.use('fivethirtyeight') # 使用 fivethirtyeight 样式 plt.plot(x, y1, label='sin(x)') plt.plot(x, y2, label='cos(x)') plt.title('使用 fivethirtyeight 样式') plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show()

内容详解:

  • plt.style.use('样式名称'): 使用指定的样式。Matplotlib内置了多种样式,例如 'default', 'ggplot', 'seaborn', 'fivethirtyeight' 等。你可以尝试不同的样式,找到最适合你的图表风格。

  • 不同的样式会影响图表的颜色、线条样式、背景、网格等各个方面,从而改变图表的整体视觉效果。

  • 你可以使用 plt.style.available 查看所有可用的样式名称。

  • 样式可以全局应用,也可以在代码块中临时应用。

1.2 颜色映射(Colormaps):用色彩表达数据维度

颜色映射(Colormap)是将数据值映射到颜色的方案。在可视化中,颜色映射常用于表示数据的密度、强度或类别。Matplotlib提供了丰富的内置颜色映射,可以根据数据特点选择合适的颜色映射,增强图表的信息表达能力。

代码实践:

import matplotlib.pyplot as plt import numpy as np # 生成示例数据 (二维高斯分布) delta = 0.025 x = np.arange(-3.0, 3.0, delta) y = np.arange(-3.0, 3.0, delta) X, Y = np.meshgrid(x, y) Z1 = np.exp(-X**2 - Y**2) Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2) Z = (Z1 - Z2) * 2 # 使用不同的颜色映射绘制热力图 plt.figure(figsize=(10, 5)) plt.subplot(1, 2, 1) plt.imshow(Z, cmap='viridis', extent=[-3, 3, -3, 3]) # 使用 'viridis' 颜色映射 plt.colorbar(label='Value') plt.title('Colormap: viridis') plt.subplot(1, 2, 2) plt.imshow(Z, cmap='coolwarm', extent=[-3, 3, -3, 3]) # 使用 'coolwarm' 颜色映射 plt.colorbar(label='Value') plt.title('Colormap: coolwarm') plt.tight_layout() plt.show()

内容详解:

  • plt.imshow(Z, cmap='颜色映射名称', extent=[xmin, xmax, ymin, ymax]): 使用 imshow 函数绘制热力图,cmap 参数指定颜色映射。

  • plt.colorbar(label='标签'): 添加颜色条,显示颜色与数据值的对应关系。

  • 'viridis', 'coolwarm', 'plasma', 'magma', 'Greys', 'Blues', 'Reds', 'Greens' 等都是常用的颜色映射。

  • 选择颜色映射时,需要考虑数据的类型和想要表达的信息。例如,'viridis' 适合表示连续数据,'coolwarm' 适合表示正负数据,'Greys' 适合表示灰度图像。

  • Matplotlib颜色映射可以分为顺序型(Sequential)、发散型(Diverging)和定性型(Qualitative)等类型,根据数据特点选择合适的类型。

1.3 文本与注解(Text and Annotations):提升图表可读性

在图表中添加文本和注解可以有效地提升图表的可读性,突出重点信息,解释数据含义。Matplotlib提供了丰富的文本和注解功能,可以灵活地在图表上添加标题、标签、文字说明、箭头指示等。

代码实践:

import matplotlib.pyplot as plt import numpy as np # 生成示例数据 x = np.linspace(0, 10, 100) y = np.sin(x) # 绘制折线图并添加文本和注解 plt.plot(x, y) plt.title('正弦波', fontsize=16, fontweight='bold') # 添加标题,设置字体大小和粗细 plt.xlabel('时间 (秒)', fontsize=12) # 添加 x 轴标签,设置字体大小 plt.ylabel('幅度', fontsize=12) # 添加 y 轴标签,设置字体大小 plt.text(2, 0.5, '峰值区域', fontsize=10, color='blue') # 在指定位置添加文本 plt.annotate('最大值', xy=(np.pi/2, 1), xytext=(2, 1.5), # 添加注解,箭头指向最大值点 arrowprops=dict(facecolor='red', shrink=0.05), fontsize=10, color='red') plt.grid(True) # 添加网格线 plt.show()

内容详解:

  • plt.title('标题文本', fontsize=字号, fontweight='字体粗细'): 添加图表标题,可以设置字体大小、粗细等属性。

  • plt.xlabel('x轴标签文本', fontsize=字号)plt.ylabel('y轴标签文本', fontsize=字号): 添加 x 轴和 y 轴标签,可以设置字体大小。

  • plt.text(x坐标, y坐标, '文本内容', fontsize=字号, color='颜色'): 在图表指定位置添加文本。

  • plt.annotate('注解文本', xy=(箭头指向点x, 箭头指向点y), xytext=(文本起始点x, 文本起始点y), arrowprops=字典, fontsize=字号, color='颜色'): 添加注解,包括箭头和文本。arrowprops 参数用于设置箭头的样式。

  • plt.grid(True): 添加网格线,辅助阅读数据。

1.4 图例(Legends):清晰标识数据系列

当图表包含多个数据系列时,图例(Legend)是必不可少的。图例可以清晰地标识每个数据系列代表的含义,帮助读者理解图表内容。

代码实践:

import matplotlib.pyplot as plt import numpy as np # 生成示例数据 x = np.linspace(0, 10, 100) y1 = np.sin(x) y2 = np.cos(x) # 绘制折线图并添加图例 plt.plot(x, y1, label='sin(x)', linestyle='-', marker='o') # 为第一个数据系列添加标签 plt.plot(x, y2, label='cos(x)', linestyle='--', marker='x') # 为第二个数据系列添加标签 plt.title('正弦波与余弦波') plt.xlabel('x') plt.ylabel('y') plt.legend() # 显示图例 plt.show()

内容详解:

  • plt.plot() 等绘图函数中,使用 label='标签文本' 参数为每个数据系列添加标签。

  • plt.legend(): 显示图例。Matplotlib会自动根据数据系列的标签生成图例。

  • 图例的位置、字体、边框等样式可以进行定制,例如 plt.legend(loc='upper right', fontsize=10, frameon=False)loc 参数控制图例位置(例如 'upper right', 'lower left', 'best' 等),frameon=False 去除图例边框。

  • 可以使用 plt.legend() 的返回值对象,进一步定制图例的细节,例如修改图例中线条的样式和颜色。

2. 多子图与复杂布局

当需要展示多个相关图表时,将它们放在同一个画布上,以子图的形式呈现,可以更有效地进行比较和分析。Matplotlib提供了多种方式创建子图,并支持灵活的布局定制。

2.1 plt.subplot(): 简单子图布局

plt.subplot() 函数是最基本的创建子图的方式。它通过指定子图的行数、列数和当前子图的索引来创建子图。

代码实践:

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.tan(x) # 创建 2x2 的子图布局 plt.figure(figsize=(8, 6)) # 创建画布,设置画布大小 plt.subplot(2, 2, 1) # 第一个子图 (2行2列,索引为1) plt.plot(x, y1) plt.title('sin(x)') plt.subplot(2, 2, 2) # 第二个子图 (2行2列,索引为2) plt.plot(x, y2) plt.title('cos(x)') plt.subplot(2, 2, 3) # 第三个子图 (2行2列,索引为3) plt.plot(x, y3) plt.title('tan(x)') plt.ylim(-5, 5) # 调整 y 轴范围,避免 tan(x) 值过大导致图表难以阅读 plt.subplot(2, 2, 4) # 第四个子图 (2行2列,索引为4) plt.plot(x, y1 + y2) plt.title('sin(x) + cos(x)') plt.tight_layout() # 自动调整子图布局,避免重叠 plt.show()

内容详解:

  • plt.figure(figsize=(宽度, 高度)): 创建画布,figsize 参数设置画布大小(英寸)。

  • plt.subplot(行数, 列数, 子图索引): 创建子图。子图索引 从 1 开始,按行优先顺序排列。

  • 每个 plt.subplot() 调用都会创建一个新的子图,后续的绘图命令将作用于当前子图。

  • plt.tight_layout(): 自动调整子图布局,避免子图之间或子图与画布边缘重叠,使图表更美观。

2.2 plt.subplots(): 更简洁的子图创建

plt.subplots() 函数是创建子图的更简洁、更推荐的方式。它一次性创建所有子图,并返回一个包含所有子图轴对象的 NumPy 数组。

代码实践:

import matplotlib.pyplot as plt import numpy as np # 生成示例数据 x = np.linspace(0, 10, 100) y1 = np.sin(x) y2 = np.cos(x) # 创建 1x2 的子图布局 fig, axes = plt.subplots(1, 2, figsize=(10, 4)) # 创建 1行2列 的子图,返回 figure 对象和 axes 数组 # axes 是一个包含两个 AxesSubplot 对象的数组 axes[0].plot(x, y1) # 使用 axes[0] 访问第一个子图轴对象 axes[0].set_title('sin(x)') axes[1].plot(x, y2) # 使用 axes[1] 访问第二个子图轴对象 axes[1].set_title('cos(x)') axes[1].set_xlabel('x') # 为第二个子图添加 x 轴标签 fig.suptitle('子图示例', fontsize=16) # 为整个 figure 添加总标题 plt.tight_layout() plt.show()

内容详解:

  • fig, axes = plt.subplots(行数, 列数, figsize=(宽度, 高度)): 创建子图布局。

    • figFigure 对象,代表整个画布。

    • axes 是一个 NumPy 数组,包含了所有子图的 AxesSubplot 对象。

  • 如果创建的是单行或单列的子图,axes 是一个一维数组;如果创建的是多行多列的子图,axes 是一个二维数组。

  • 通过 axes[索引]axes[行索引, 列索引] 可以访问到具体的子图轴对象,然后使用轴对象的方法(例如 axes[0].plot(), axes[1].set_title())在对应的子图上绘图和设置属性。

  • fig.suptitle('总标题文本', fontsize=字号): 为整个 figure 添加总标题。

2.3 GridSpec: 更灵活的复杂布局

GridSpec 提供了更强大的子图布局控制能力,可以创建更复杂的、非均匀的子图布局。例如,可以创建子图跨越多行或多列,或者创建不规则形状的子图布局。

代码实践:

import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import numpy as np # 生成示例数据 x = np.linspace(0, 10, 100) y1 = np.sin(x) y2 = np.cos(x) y3 = np.tan(x) # 创建 GridSpec 对象,定义布局 gs = gridspec.GridSpec(3, 3) # 创建 3x3 的网格布局 # 创建 figure 和 axes fig = plt.figure(figsize=(10, 8)) # 使用 GridSpec 创建子图并指定位置 ax1 = fig.add_subplot(gs[0, :]) # 第 1 行,跨越所有列 ax1.plot(x, y1) ax1.set_title('gs[0, :]') ax2 = fig.add_subplot(gs[1, :-1]) # 第 2 行,跨越除最后一列外的所有列 ax2.plot(x, y2) ax2.set_title('gs[1, :-1]') ax3 = fig.add_subplot(gs[1:, -1]) # 跨越从第 2 行到最后一行,最后一列 ax3.plot(y3, x) # 注意 x 和 y 轴数据互换,让 tan(x) 图形竖直显示 ax3.set_title('gs[1:, -1]') ax3.set_ylim(-5, 5) # 调整 y 轴范围 ax4 = fig.add_subplot(gs[2, 0]) # 第 3 行,第 1 列 ax4.plot(x, y1 + y2) ax4.set_title('gs[2, 0]') ax5 = fig.add_subplot(gs[2, 1]) # 第 3 行,第 2 列 ax5.plot(x, y1 * y2) ax5.set_title('gs[2, 1]') plt.tight_layout() plt.show()

内容详解:

  • import matplotlib.gridspec as gridspec: 导入 gridspec 模块。

  • gs = gridspec.GridSpec(行数, 列数): 创建 GridSpec 对象,定义网格布局。

  • fig.add_subplot(gs[行索引, 列索引]): 使用 GridSpec 对象创建子图。

    • gs[行索引, 列索引] 可以使用切片(slice)来指定子图跨越的行和列范围。例如:

      • gs[0, :] 表示第一行所有列。

      • gs[:, 0] 表示第一列所有行。

      • gs[1:, :-1] 表示从第二行到最后一行,除了最后一列的所有列。

  • GridSpec 提供了更灵活的子图布局控制,可以创建各种复杂的图表布局。

mermaid graph TD 图示 GridSpec 布局:

3. 三维绘图

Matplotlib 可以进行三维绘图,通过 mpl_toolkits.mplot3d 工具包,可以创建三维散点图、曲面图、线框图等,可视化三维数据。

代码实践:

import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 导入 3D 绘图工具 import numpy as np # 创建 figure 和 3D axes fig = plt.figure(figsize=(8, 6)) ax = fig.add_subplot(projection='3d') # 指定 projection='3d' 创建 3D 轴 # 三维散点图 z = np.linspace(0, 1, 100) x = np.sin(z * 2 * np.pi) y = np.cos(z * 2 * np.pi) ax.scatter(x, y, z, c=z, cmap='viridis') # c=z 使用 z 值作为颜色,cmap 指定颜色映射 ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_title('3D Scatter Plot') plt.show()

内容详解:

  • from mpl_toolkits.mplot3d import Axes3D: 导入 Axes3D 类,用于创建 3D 轴对象。

  • ax = fig.add_subplot(projection='3d'): 在 figure 中添加一个 3D 子图,通过 projection='3d' 参数指定创建 3D 轴。

  • ax.scatter(x, y, z, c=颜色数据, cmap='颜色映射'): 绘制三维散点图。

    • x, y, z 分别是数据点的 x, y, z 坐标。

    • c 参数可以指定每个点的颜色,可以使用一维数组,例如 c=z,表示使用 z 值作为颜色。

    • cmap 参数指定颜色映射。

  • ax.set_xlabel('X'), ax.set_ylabel('Y'), ax.set_zlabel('Z'): 设置三维坐标轴标签。

  • 除了 scatter()mpl_toolkits.mplot3d 还提供了 plot_surface() (曲面图), plot_wireframe() (线框图), contour3D() (三维等高线图) 等函数,用于绘制不同类型的三维图表。

三维曲面图示例:

import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np # 创建 figure 和 3D axes fig = plt.figure(figsize=(8, 6)) ax = fig.add_subplot(projection='3d') # 生成网格数据 num1 = np.arange(-3, 3, 0.1) num2 = np.arange(-3, 3, 0.1) X, Y = np.meshgrid(num1, num2) # 定义 Z 轴数据 (例如,高斯函数) Z = np.exp(-(X**2 + Y**2) / 2) # 绘制三维曲面图 ax.plot_surface(X, Y, Z, cmap='viridis') # 绘制曲面图 ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_title('3D Surface Plot') plt.show()

4. 高级图表类型

除了常见的折线图、散点图和柱状图,Matplotlib 还支持一些更高级的图表类型,用于可视化特定类型的数据和关系。

4.1 等高线图(Contour Plots):可视化三维表面的二维投影

等高线图是将三维表面投影到二维平面上,用等高线表示表面高度的图表。常用于地理数据、地形图、气象图等领域。

代码实践:

import matplotlib.pyplot as plt import numpy as np # 生成网格数据 (与三维曲面图示例相同) delta = 0.025 x = np.arange(-3.0, 3.0, delta) y = np.arange(-2.0, 2.0, delta) X, Y = np.meshgrid(x, y) Z1 = np.exp(-X**2 - Y**2) Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2) Z = (Z1 - Z2) * 2 # 绘制等高线图 plt.figure(figsize=(8, 6)) CS = plt.contour(X, Y, Z, 20, cmap='RdBu') # 绘制等高线,20 表示等高线数量,cmap 指定颜色映射 plt.clabel(CS, inline=True, fontsize=8) # 添加等高线标签,inline=True 表示标签在线条内部 plt.title('Contour Plot') plt.xlabel('X') plt.ylabel('Y') plt.show()

内容详解:

  • plt.contour(X, Y, Z, levels=等高线数量, cmap='颜色映射'): 绘制等高线图。

    • X, Y 是网格点的 x, y 坐标。

    • Z 是网格点的高度值。

    • levels 参数指定等高线数量或具体的等高线高度值列表。

    • cmap 参数指定颜色映射,用于填充等高线之间的区域,或者给等高线本身着色。

  • plt.clabel(CS, inline=True, fontsize=字号): 添加等高线标签,显示等高线的高度值。 CSplt.contour() 函数的返回值。

4.2 热力图(Heatmaps):可视化矩阵数据的密度或强度

热力图使用颜色来表示矩阵数据的值,颜色深浅程度与数据值大小成正比。常用于可视化相关性矩阵、基因表达数据、网页点击热度等。

代码实践:

import matplotlib.pyplot as plt import numpy as np # 生成随机矩阵数据 data = np.random.rand(10, 10) # 绘制热力图 plt.figure(figsize=(8, 6)) heatmap = plt.imshow(data, cmap='plasma', interpolation='nearest') # 绘制热力图,cmap 指定颜色映射,interpolation 指定插值方式 plt.colorbar(heatmap, label='Value') # 添加颜色条 plt.title('Heatmap') plt.xlabel('Columns') plt.ylabel('Rows') plt.xticks(np.arange(10)) # 设置 x 轴刻度 plt.yticks(np.arange(10)) # 设置 y 轴刻度 plt.show()

内容详解:

  • plt.imshow(data, cmap='颜色映射', interpolation='插值方式'): 绘制热力图。

    • data 是二维矩阵数据。

    • cmap 参数指定颜色映射。

    • interpolation 参数指定插值方式,影响热力图的平滑程度。 'nearest' 表示最近邻插值,'bilinear' 表示双线性插值等。

  • plt.colorbar(heatmap, label='标签'): 添加颜色条,显示颜色与数据值的对应关系。 heatmapplt.imshow() 函数的返回值。

  • plt.xticks(刻度位置列表)plt.yticks(刻度位置列表): 设置 x 轴和 y 轴刻度。

4.3 流场图/矢量场图(Stream Plots/Quiver Plots):可视化矢量场

流场图(Stream Plot)和矢量场图(Quiver Plot)用于可视化矢量场数据,例如流体流动、电场、磁场等。流场图用流线表示矢量场的方向和强度,矢量场图用箭头表示矢量场的方向和强度。

代码实践 (流场图):

import matplotlib.pyplot as plt import numpy as np # 生成矢量场数据 (例如,一个简单的旋转矢量场) x = np.linspace(-3, 3, 50) y = np.linspace(-3, 3, 50) X, Y = np.meshgrid(x, y) U = -Y # x 方向分量 V = X # y 方向分量 # 绘制流场图 plt.figure(figsize=(8, 6)) plt.streamplot(X, Y, U, V, density=1.5, linewidth=0.8, cmap='viridis') # 绘制流场图 plt.title('Stream Plot') plt.xlabel('X') plt.ylabel('Y') plt.show()

发布者: 作者: 转发
评论区 (0)
U