Matplotlib 3.0 秘籍(一)
零、前言
在大数据时代,寻找有价值的业务见解类似于在大海捞针。 可视化在不断增加的数据量和各种数据中找到这些块时起着至关重要的作用。 Matplotlib 凭借其丰富的可视化功能,使探索性数据分析过程变得用户友好且更加高效。
Matplotlib 的核心功能非常强大,许多内部和第三方辅助工具包进一步增强了。 市场上的任何书籍都仅覆盖其全部功能的一小部分。 在本书中,我们介绍了 Matplotlib 的完整核心功能及其许多流行的工具包。
Matplotlib 在使用 Python 生态系统的机器学习从业人员和研究人员中很受欢迎。 凭借其丰富的功能,它可以用于商业智能和运营报告应用。 在本书中,我们尝试介绍这些应用中的示例。
尽管基于秘籍的秘籍方法使本书成为快速解决方案的参考指南,但我们已经涵盖了足够的理论背景,对于初学者来说也很容易。
这本书是给谁的
本书适用于数据分析师,业务分析师,数据科学家和 Python 开发人员,他们正在为各种可视化应用寻求快速解决方案,例如临时报告,专业仪表板,探索性数据分析,交互分析,选定中的嵌入式可视化文件 GUI 工具箱和 Web 应用,三维图和地理地图。
那些对开发商业智能,机器学习,科学或工程应用感兴趣的人也会从与这些学科相关的秘籍中受益。
充分利用这本书
除了第 9 章,“开发交互式绘图”和第 10 章,“嵌入图形用户界面”外,Python 的基本知识足以理解本书的内容。 。 这两章介绍需要中级 Python 编程经验的交互式绘图和嵌入式应用。
许多 Python 发行版自动包含 Matplotlib 及其所有依赖项。 如果尚未安装任何标准的 Python 发行版,则可以在这个页面上按照的安装过程来安装 Matplotlib 及其相关的依赖项。
使用约定
本书中使用了许多文本约定。
CodeInText:表示文本中的词,数据库表名称,文件夹名称,文件名,文件扩展名,路径名,伪 URL,用户输入和 Twitter 句柄。 例如:“我们将按照.txt,.csv和.xlsx文件,分为三个部分。”
代码块设置如下:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from matplotlib import cm
粗体:表示您在屏幕上看到的新术语,重要单词或顺序。 例如,菜单或对话框中的单词会出现在这样的文本中。 这是一个示例:“当您运行程序并单击下一步时,您将看到以下三个图,代表每个群集,如每个标题中所示。”
Warnings or important notes appear like this.Tips and tricks appear like this.
标题
在本书中,您会发现几个经常出现的标题(“准备”,“操作步骤”,“工作原理”,和“另见”)。
要给出有关如何完成秘籍的明确说明,请按以下说明使用这些部分:
准备
本节告诉您在秘籍中会有什么期望,并介绍如何设置秘籍所需的任何软件或任何初步设置。
操作步骤
本节包含遵循秘籍所需的步骤。
工作原理
本节通常包括对上一节中发生的情况的详细说明。
更多
本节包含有关秘籍的其他信息,以使您对秘籍有更多的了解。
另见
本节提供了指向该秘籍其他有用信息的有用链接。
一、Matplotlib 的剖析
本章从 Matplotlib 的介绍开始,包括 Matplotlib 的架构和图形元素,然后是秘籍。 以下是本章将介绍的秘籍:
- 在交互模式下工作
- 在非交互模式下工作
- 从外部文件读取并绘图
- 如何更改和重置默认环境变量
介绍
Matplotlib 是一个跨平台的 Python 库,用于绘制二维图形(也称为图)。 它可以在各种用户界面中使用,例如 Python 脚本,IPython Shell,Jupyter 笔记本,Web 应用和 GUI 工具包。 它可以用于开发专业的报表应用,交互式分析应用,复杂的仪表板应用或嵌入到 Web/GUI 应用中。 它还支持将图形保存为各种硬拷贝格式。 它还对三维图形的支持有限。 它还支持许多第三方工具包以扩展其功能。
请注意,本书中的所有示例均已通过 Matplotlib 3.0 和 Jupyter Notebook 5.1.0 进行了测试。
Matplotlib 的架构
Matplotlib 具有三层架构:后端,艺术家和脚本,它们在逻辑上组织为栈。 脚本是开发人员用来创建图形的 API。 美工完成了内部创建图形的实际工作。 后端是显示图形的位置。
后端层
这是图形显示在输出设备上的最底层。 这可以是 Matplotlib 支持的任何用户界面。 后端有两种类型:用户界面后端(用于pygtk,wxpython,tkinter,qt4或macosx等,也称为交互式后端)和硬拷贝后端,以制作图像文件(.png,.svg,.pdf和.ps,也称为非交互式后端)。 我们将在稍后的第 9 章,“开发交互式绘图”和第 10 章,“将图形嵌入图形用户界面”中学习如何配置这些后端。
艺术家层
这是栈的中间层。 Matplotlib 使用artist对象绘制图形的各种元素。 因此,我们在图形中看到的每个元素(请参见图中的元素)都是一个艺术家。 该层提供了面向对象的 API ,以最大的灵活性来绘制图形。 该接口适用于经验丰富的 Python 程序员,他们可以创建复杂的仪表板应用。
脚本层
这是栈的最顶层。 该层提供了用于创建图形的简单接口。 这供没有太多编程专业知识的最终用户使用。 这称为pyplot API。
图元素
包含输出图的所有元素的高级 Matplotlib 对象称为figure。 可以以不同方式排列多个图形以形成图形。 图的每个元素都是可自定义的。
图形
下图是figure的剖析图,其中包含其所有元素:
Anatomy of a figure (Source : diagramss.us/plotting-a-…)
轴域
axes是该图的子部分,其中绘制了图形。axes具有标题,x 标签和 y 标签。figure可以具有许多这样的axes,每个figure代表一个或多个图形。 在上图中,只有一个axes,两个是蓝色和红色的折线图。
轴
这些是数字线,代表要绘制的图形的比例。 二维图具有 x 轴和 y 轴,而三维图具有 x 轴, y 轴 ,以及 z 轴。
Don't get confused between axes and axis. Axis is an element of axes. Grammatically, axes is also the plural for axis, so interpret the meaning of axes depending on the context, whether multiple axis elements are being referred to or an axes object is being referred to.
标签
这是图中各个元素的名称,例如 x 轴标签, y 轴标签,图形标签(上图中的蓝色信号/红色信号图形剖析等等。
图例
当axes中有多个图形时(如上图,图形剖析图),每个图形都有其自己的标签,所有这些标签均表示为图例。 在上图中,图例位于图的右上角。
标题
它是每个axes的名称。 当图形具有多个带有各自标题的轴域时,figure也可以具有自己的标题。 上图只有一个轴域,因此轴域和该图都只有一个标题。
刻度标签
每个轴(x,y 或 z)都有一个范围的值,该值分为许多相等的桶。 桶分为两个级别。 在上一个图(剖析图), x 轴刻度范围从 0 到 4,分为四个主要区域(0-1、1-2、2-3 和 3-4),每个主要桶又分为四个次要桶(0-0.25、0.25-0.5 和 0.5-0.75)。 主桶两侧的刻度称为主刻度,次桶称为次刻度,它们的名称为主刻度标签和次刻度标签。
轴线
该图的边界称为轴线。 每个轴域有四个轴线(上,下,左和右)。
网格
为了更容易读取图形上各个点的坐标,将图形区域划分为网格。 通常,此网格沿着 x 和 y 轴的主要刻度线绘制。 在上图中,以虚线显示了网格。
在交互模式下工作
Matplotlib 可以在交互式或非交互式模式下使用。 在交互模式下,每条语句后图形显示都会更新。 在非交互模式下,只有明确要求这样做,图形才会显示。
准备
您需要 Python,NumPy 和 Matplotlib 包的有效安装。
使用以下命令,可以打开或关闭交互模式,还可以在任何时间点检查当前模式:
matplotlib.pyplot.ion()设置交互模式ONmatplotlib.pyplot.ioff()切换OFF交互模式matplotlib.is_interactive()检查交互模式是ON(True)还是OFF(False)
操作步骤
让我们看看在交互模式下工作有多么简单:
- 将屏幕输出设置为后端:
%matplotlib inline
- 导入
matplotlib和pyplot库。 在 Python 中,通常的做法是导入带有清晰同义词的库。 注意plt是matplotlib.pyplot包的同义词:
import matplotlib as mpl import matplotlib.pyplot as plt
- 将交互模式设置为开:
plt.ion()
- 检查交互模式的状态:
mpl.is_interactive()
- 您应该得到的输出为
True。 - 绘制折线图:
plt.plot([1.5, 3.0])
您应该看到以下图形作为输出:
- 现在,借助以下代码,将轴标签和标题添加到图形中:
## Add labels and title
plt.title("Interactive Plot") #Prints the title on top of graph
plt.xlabel("X-axis") # Prints X axis label as "X-axis"
plt.ylabel("Y-axis") # Prints Y axis label as "Y-axis"
执行上述三个语句后,图形应如下所示:
工作原理
因此,这就是解释的方式:
plt.plot([1.5, 3.0])绘制连接两个点(0, 1.5)和(1.0, 3.0)的折线图。plot命令需要两个参数(分别为x和y轴,使用 Python 列表,NumPy 数组或 pandas 数据帧)。 。- 如果仅传递一个参数,则将其作为 y 轴坐标,而对于 x 轴坐标,它将采用所提供参数的长度。
- 在此示例中,我们仅传递两个点的一个列表,这些列表将作为 y 轴坐标。
- 对于 x 轴,由于列表
[1.5, 3.0]的长度为 2,因此它采用的默认值为 0 到 1。 - 如果我们在 y 的列表中有三个坐标,那么对于 x,它将取 0 到 2 的范围。
- 您应该看到类似于步骤 6 中显示的图形。
plt.title("Interactive Plot"),将标题作为"Interactive Plot"打印在图形顶部**。plt.xlabel("X-axis"),将 x 轴标签打印为"X-axis"。plt.ylabel("Y-axis"),将 y 轴标签打印为"Y-axis"。- 执行完前面的三个语句后,您应该看到如图步骤 7 中所示的图形。
如果您使用的是 Python Shell,则在执行每个代码语句后,您应该首先看到图形标题已更新,然后是 x 轴标签,最后是 y 轴标签 。
如果您使用的是 Jupyter 笔记本,则只有在执行给定单元格中的所有语句后才能看到输出,因此您必须将这三个语句中的每一个放在单独的单元格中,然后一个接一个地执行,以查看绘图在每个代码语句之后被更新。
In older versions of Matplotlib or certain backends (such as macosx), the graph may not be updated immediately. In such cases, you need to call plt.draw() explicitly at the end, so that the graph gets displayed.
更多
您可以在同一图上再添加一个折线图,然后继续进行直到完成交互式会话:
- 绘制折线图:
plt.plot([1.5, 3.0])
- 添加标签和标题:
plt.title("Interactive Plot")
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
- 再添加一个折线图:
plt.plot([3.5, 2.5])
下图是执行代码后获得的输出:
因此,我们现在在交互模式下工作。
在非交互模式下工作
在交互模式下,我们看到了随着每条指令逐步构建的图形。 在非交互模式下,您将提供所有说明来构建图形,然后使用命令显式显示图形。
操作步骤
在非交互模式下工作也不困难:
- 重新启动内核,并导入
matplotlib和pyplot库:
import matplotlib
import matplotlib.pyplot as plt
- 将交互模式设置为关闭:
plt.ioff()
- 检查交互模式的状态:
matplotlib.is_interactive()
- 您应该获得输出
False。 - 执行以下代码; 您不会在屏幕上看到该图:
## Plot a line graph
plt.plot([1.5, 3.0])
## Plot the title, X and Y axis labels
plt.title("Non Interactive Mode")
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
- 执行以下语句,然后您将在屏幕上看到该图:
## Display the graph on the screen
plt.show()
工作原理
前面的每个代码语句都是不言自明的。 要注意的重要事项是在非交互模式下,为要显示的图形编写完整的代码,然后显式调用plt.show()以在屏幕上显示图形。
以下是获得的输出:
The latest versions of Jupyter Notebook seem to display the figure without calling
plt.show() command explicitly. However, in Python shell or embedded applications, plt.show() or plt.draw() is required to display the figure on the screen.
从外部文件读取并绘图
默认情况下,Matplotlib 接受输入数据作为 Python 列表,NumPy 数组或 pandas 数据帧。 因此,需要先读取所有外部数据并将其转换为这些格式之一,然后再将其提供给 Matplotlib 进行图形绘制。 从性能的角度来看,NumPy 格式更有效,但对于默认标签,pandas 格式比较方便。
如果数据是.txt文件,则可以使用 NumPy 函数读取数据并将其放入 NumPy 数组中。 如果数据为.csv或.xlsx格式,则可以使用 Pandas 读取数据。 在这里,我们将演示如何读取.txt,.csv和.xlsx格式,然后绘制图表。
准备
导入读取输入文件所需的matplotlib.pyplot,numpy和pandas包:
- 导入具有
plt同义词的pyplot库:
import matplotlib.pyplot as plt
- 导入具有
np同义词的numpy库。numpy库可以管理 n 维数组,支持这些数组上的所有数学运算:
import numpy as np
- 以
pd作为同义词导入pandas包:
import pandas as pd
操作步骤
我们将在三个单独的部分中遵循.txt,.csv和.xlsx文件的顺序。
从.txt文件读取
以下是一些步骤:
- 将文本文件读入
txt变量:
txt = np.loadtxt('test.txt', delimiter = ',')
txt
这是前面代码块的说明:
test.txt文本文件有 10 个数字,用逗号隔开,代表二维空间中的 x 和 y 五个点的坐标(1, 1),(2, 4),(3, 9),(4, 16)和(5, 25)。- 函数
loadtxt()和将文本数据加载到 NumPy 数组中。
您应该获得以下输出:
array([ 1., 1., 2., 4., 3., 9., 4., 16., 5., 25.])
- 将平面数组转换为 2D 空间中的五个点:
txt = txt.reshape(5,2)
txt
执行前面的代码后,您应该看到以下输出:
array([[ 1., 1.], [ 2., 4.], [ 3., 9.], [ 4., 16.], [ 5., 25.]])
- 将
.txt变量拆分为x和y轴坐标:
x = txt[:,0]
y = txt[:,1]
print(x, y)
这是前面代码块的解释:
- 将
x和y轴点与txt变量分开。 x是txt中的第一列,y是第二列。- Python 索引从 0 开始。
执行上述代码后,您应该看到以下输出:
[ 1\. 2\. 3\. 4\. 5.] [ 1\. 4\. 9\. 16\. 25.]
从.csv文件读取
.csv文件具有行和列的关系数据库结构,test.csv文件在 2D 空间中具有五个点的 x,y 坐标。 每个点是文件中的一行,分为两列:x和y。 相同的 NumPy loadtxt()函数用于加载数据:
x, y = np.loadtxt ('test.csv', unpack = True, usecols = (0,1), delimiter = ',')
print(x)
print(y)
执行上述代码后,应该看到以下输出:
[ 1\. 2\. 3\. 4\. 5.] [ 1\. 4\. 9\. 16\. 25.]
从.xlsx文件读取
现在,让我们从.xlsx文件中读取相同的数据,并创建x和y NumPy 数组。 NumPy loadtxt()函数不支持.xlsx文件格式。 可以使用 Python 数据处理包pandas:
- 将
.xlsx文件读入 pandas 数据帧中。 该文件在 2D 空间中具有相同的五个点,每个点在具有x和y列的单独行中:
df = pd.read_excel('test.xlsx', 'sheet', header=None)
- 将 pandas 数据帧转换为 NumPy 数组:
data_array = np.array(df)
print(data_array)
您应该看到以下输出:
[[ 1 1] [ 2 4] [ 3 9] [ 4 16] [ 5 25]]
- 现在从 NumPy 数组中提取
x和y坐标:
x , y = data_array[:,0], data_array[:,1]
print(x,y)
您应该看到以下输出:
[1 2 3 4 5] [ 1 4 9 16 25]
绘制图形
从三种格式(.txt,.csv和.xlsx)中的任何一种读取数据并将其格式化为x和y变量后,我们使用以下变量绘制图形:
plt.plot(x, y)
在屏幕上显示图形:
plt.show()
以下是获得的输出:
工作原理
根据数据的格式和结构,我们将不得不使用 Python,NumPy 或 pandas 函数来读取数据并将其重新格式化为可以馈入matplotlib.pyplot函数的适当结构。 之后,按照通常的绘制说明绘制所需的图形。
更改和重置默认环境变量
Matplotlib 使用matplotlibrc文件存储跨 matplotlib 功能使用的各种环境和图形参数的默认值。 注意,该文件很长。 这些默认值可自定义以应用于会话中的所有绘图。
可以使用print(matplotlib.rcParams)命令从该文件获取所有默认参数设置。
matplotlib.rcParams命令用于将这些默认值更改为任何其他支持的值,一次更改一个参数。matplotlib.rc命令用于为特定组中的多个参数设置默认值,例如,行,字体,文本等。 最后,matplotlib.rcdefaults()命令用于恢复默认参数。
Matplotlib 在内部使用matplotlib.rcsetup()命令来验证所更改的参数是可接受的值。
准备
以下代码块提供了包含所有配置参数的文件路径:
## Get the location of matplotlibrc file
import matplotlib
matplotlib.matplotlib_fname()
您应该看到类似下面的目录路径。 确切的目录路径取决于您的安装:
'C:\\Anaconda3\\envs\\keras35\\lib\\site-packages\\matplotlib\\mpl-
data\\matplotlibrc'
操作步骤
以下代码块以及注释可帮助您了解更改和重置默认环境变量的过程:
- 导入具有
plt同义词:的matplotlib.pyplot包
import matplotlib.pyplot as plt
- 从我们在前面的秘籍中使用的同一
test.csv文件中加载x和y变量:
x, y = np.loadtxt ('test.csv', unpack = True, usecols = (0,1),
delimiter = ',')
- 更改组
'lines'中多个参数的默认值:
matplotlib.rc('lines', linewidth=4, linestyle='-', marker='*')
- 分别更改参数的默认值:
matplotlib.rcParams['lines.markersize'] = 20
matplotlib.rcParams['font.size'] = '15.0'
- 绘制图形:
plt.plot(x,y)
- 显示图形:
plt.show()
以下是将获得的输出:
工作原理
matplotlib.rc和matplotlib.rcParams命令覆盖指定参数的默认值作为这些命令中的参数。 在绘制图形时,pyplot工具将使用这些新值。
It should be noted that these values will be active for all plots in the session. If you want different settings for each plot in the same session, then you should use the attributes available with the plot command.
更多
您可以使用rsdefaults()命令将所有参数重置为其默认值,如下框所示:
## To restore all default parameters
matplotlib.rcdefaults()
plt.plot(x,y)
plt.show()
该图如下所示:
.
十、使用mplot3d工具包绘制 3D 图形
在本章中,我们将介绍绘制以下图形的方法:
- 线形图
- 散点图
- 条形图
- 多边形图
- 等高线图
- 曲面图
- 线框图
- 三角曲面图
- 在 3D 模式下绘制 2D 数据
- 在 3D 中可视化 2D 中的线性不可分离数据
- 绘制单词嵌入
介绍
Matplotlib 的早期版本仅限于 2D 绘图,后来又将 3D 功能添加为附加工具箱:mplot3d。 尽管它具有有限的 3D 功能,但它涵盖了 3D 绘图的大多数常见业务需求。
绘图命令与 2D 命令相似。 只是我们向 Matplotlib 注册,我们将通过从工具包中导入Axes3D来使用 3D 图,并在轴域定义中指定projection='3d'。
如果您正在使用任何交互式后端,还可以通过将图形拖向所需的任何方向来旋转 3D 图片以获取不同的视图。 您还可以通过在帧之间稍稍停顿的情况下旋转图形来创建动画。 我们将学习如何在某些图中使用这些功能,尽管它们可以应用于所有图中。
线形图
在本秘籍中,我们将学习如何创建 3D 线形图。 它类似于 2D 等效折线图,并且 2D 折线图的和属性中的许多属性都将结转到 3D。
我们将在相同的轴域上绘制凹凸曲线,并从不同角度查看它们,例如平行视图,俯视图以及绕, z 轴旋转。
准备
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
操作步骤
以下是绘制 3D 折线图的步骤:
- 准备 x,y 和 z 轴坐标的数据:
x = np.linspace(-5, 5, 25)
y = np.linspace(-5, 5, 25)
z = x**2 + y**2
z1 = 1 - (x**2 + y**2)
- 定义一个函数来绘制图形并设置其属性:
def plot_graph(axes, xlabel, ylabel, zlabel, title, elevation, rotation):
axes.plot3D(x, y, z, label='concave')
axes.plot(x, y, z1, label='convex')
axes.view_init(elev=elevation, azim=rotation)
axes.set_xlabel(xlabel)
axes.set_ylabel(ylabel)
axes.set_zlabel(zlabel)
axes.set_title(title)
axes.legend(loc='best')
- 定义用于 3D 绘图的图形和轴域
ax1:
fig = plt.figure(figsize=(15,9))
ax1 = fig.add_subplot(231, projection='3d')
- 用默认高度和旋转度在
ax1上绘制曲线:
plot_graph(ax1, 'X', 'Y', 'Z', 'default view', None, None)
- 定义第二个轴域
ax2并以 0 度的仰角绘制它,并以默认的azimuth角进行绘制:
ax2 = fig.add_subplot(232, projection='3d')
plot_graph(ax2, 'X', 'Y', 'Z', 'elevation angle = 0,\n azimuth angle=None', 0, None)
- 定义第三个轴域
ax3并以 90 度仰角绘制它,并以默认azimuth缺省角度进行绘制:
ax3 = fig.add_subplot(233, projection='3d')
plot_graph(ax3, 'X', 'Y', ' ', 'elevation angle = 90,\n azimuth angle=None', 90, None)
ax3.set_zticks([])
- 定义第四个轴域
ax4,并使用默认仰角和-30度的方位角进行绘制:
ax4 = fig.add_subplot(234, projection='3d')
plot_graph(ax4, 'X', 'Y', 'Z', 'elevation angle = None,\n azimuth angle=-30', None, -30)
- 定义第五个轴域
ax5,并使用默认仰角和30度的方位角进行绘制:
ax5 = fig.add_subplot(235, projection='3d')
plot_graph(ax5, 'X', 'Y', 'Z', 'elevation angle = None,\n azimuth
angle=30', None, 30)
- 调整绘图之间的空间,并将其显示在屏幕上:
plt.tight_layout(w_pad=5)
plt.show()
工作原理
这是前面的代码块的说明:
x = np.linspace(−5, 5, 25)创建一个数组,该数组的 25 个点在 -5 和 +5 之间等距分布,并且z和z1被定义为x和ydef plot_graph(axes, xlabel, ylabel, zlabel, title, elevation, rotation):是用于绘制具有给定属性的图形的函数:axes指定要在其上绘制图形的轴域。xlabel,ylabel和zlabel分别为 x,y 和 z 轴指定标签。title指定图的标题。elevation指定相对于 xy 平面的视角:0 表示平行于 xy 平面的视角,90 表示俯视图。rotation指定在 z 轴上旋转的绘图的视图。elevation和rotation均以度为单位。axes.plot3D(x, y, z, label='concave')与 2D 线形图语法相似,不同之处在于,我们还包括 z 轴。 您也可以使用axes.plot()代替axes.plot3D(),就像我们对凸曲线所做的那样。 大多数其他绘图也是如此,但并非所有情况都如此。axes.view_init(elev=elevation, azim=rotation)指定绘图出现时的视图。- 函数中的其余语句已经为我们所熟悉。
ax1 = fig.add_subplot(231, projection='3d')在图形上添加了一个轴域,其布局指定为2 x 3网格:projection='3d'指定它为 3D 轴域,并在其上绘制三维图。 这是 2D 和 3D 绘图语法之间的主要区别。
- 在
ax1上,我们使用默认仰角和旋转角度绘制图表 - 在
ax2至ax4上,我们绘制了具有不同仰角和旋转角度的相同图形,以查看其视图的差异。
在执行前面的代码时,您应该在屏幕上看到以下图形和绘图:
散点图
在本秘籍中,我们将学习如何在 3D 中绘制散点图。 在此示例中,我们将使用Iris数据集,该数据集具有三个不同的群集。 在前面的章节中,我们已经多次在 2D 中看到它,所以让我们看看它在 3D 中的外观。
我们还将学习如何使用在前面的秘籍中学习的init_view方法创建动画 3D 绘图。 为此,我们需要使用任何后端,因为动画无法与嵌入式显示器%matplotlib inline一起使用。
准备
设置所需的后端:
import matplotlib
matplotlib.use('tkAgg')
导入所需的库:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
操作步骤
以下是实现逻辑的步骤:
- 加载并准备 3D 图的数据:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" : 1, "virginica" : 2})
x, y, z = iris['petal_length'], iris['petal_width'], iris['species']
- 定义并实例化图形和轴域以进行 3D 绘图:
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111, projection='3d')
- 使用
for循环绘制散点图,以绘制具有不同颜色和标记的每个聚类:
for name, c, marker in zip((0, 1, 2), ('r', 'b', 'g'), ('o', '^', '*')):
index = iris['species'] == name
ax.scatter(x[index], y[index], z[index], s=25*x[index]*y[index],
c=c, marker=marker)
- 设置图形的标签:
ax.set_xlabel('petal length')
ax.set_ylabel('petal width')
ax.set_zlabel('species')
ax.set_zticks([0, 1, 2])
- 定义一个循环以创建 3D 图动画:
for angle in range(0, 360):
ax.view_init(30, angle)
plt.pause(.001)
- 在 Tkinter 后端上显示动画图形:
plt.show();
工作原理
这是前面代码的解释:
matplotlib.use('tkAgg')将后端设置为 Tkinter。x, y, z = iris['petal_length'], iris['petal_width'], iris['species']为 x,y 和 z 坐标准备数据。 我们在 x 和 y 轴域上绘制*petal_length*和petal_width,然后在 z 轴域上绘制species(簇号)。ax.scatter(x[index], y[index], z[index], s=25*x[index]*y[index], c=c, marker=marker)与 2D 散点图语法相似,不同之处在于,我们还包括 z 轴。- 要创建动画,我们使用
for循环,并将视图旋转角度从 0 更改为 360 度:ax.view_init(30, angle)使仰角固定为 30 度,并在每次迭代中将旋转角改变 1 度plt.pause(.001)在两次迭代之间暂停 0.001 秒
执行上述代码后,您应该会在一个新窗口中看到一个动画图,该窗口以 Tkinter 后端打开。 该图的静态版本应类似于此处所示:
条形图
在本秘籍中,我们将学习如何在 3D 模式下绘制条形图。 我们将使用电池销售数据,该数据已在第 2 章和“基本绘图”入门中用于表格绘制。 在这里,我们只会在条形图下方绘制条形图,而不是表格图。
准备
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
操作步骤
以下是实现逻辑的步骤:
- 定义用于 3D 绘图的图形和轴域:
fig = plt.figure(figsize=(10,6))
ax = fig.add_subplot(111, projection='3d')
- 准备 x,y 和 z 轴的数据:
## Years for which we have battery sales data
x = [2011, 2012, 2013, 2014, 2015]
## Repeat X, 5 times to represent each of the 5 battery ratings
X = x * 5
## List of Battery ratings
battery_ratings = ['7Ah', '35Ah', '40Ah', '135Ah', '150Ah']
## Number of units sold each year, each rating. e.g. 75 units of 7Ah(0) batteries, 144 units of 35Ah(1) #batteries sold in 2011
Y = np.array([[75, 144, 114, 102, 108],
[90, 126, 102, 84, 126],
[96, 114, 75, 105, 135],
[105, 90, 175, 90, 75],
[90, 75, 135, 75, 90]])
## Represent battery rating in numeric codes
yticks = [0, 1, 2, 3, 4]
## Use different color for each of the battery ratings
colors = ['r', 'g', 'b', 'y', 'm']
- 绘制条形图:
i=0
for c, k in zip(colors, yticks):
cs = [c] * len(X)
ax.bar(X[i:i+5], Y[:,int(i/5)], zs=k, zdir='y', color=cs,
alpha=0.8)
i += 5
- 设置图表的标签:
ax.set_yticks(yticks)
ax.set_yticklabels(battery_ratings)
ax.set_xlabel('Year')
ax.set_ylabel('Battery Type')
ax.set_zlabel('Units Sold')
- 在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
-
x 和 y 是长度为 25 的列表,分别代表年份和所售单位的数量。
-
yticks以数字格式表示电池额定值,将在 y 轴上标出。 -
colors是连续用于和电池额定值中每种颜色的五种颜色的列表。 -
for循环在每次迭代中连续绘制一项电池额定数据。 -
cs = [c] * len(X)创建一个长度为X的相同颜色c的列表。 -
ax.bar(X[i:i+5], Y[:,int(i/5)], zs=k, zdir='y', color=cs, alpha=0.8)绘制,条形图:- 从
X和Y数组中提取每种电池类型的五个元素(代表五年),以绘制一行横条。 zs=k指定将数字电池额定值映射到 z 轴。zdir='y'指定交换 z 和 y 轴,以便在 y 轴绘制Z数据。 在 z 轴域上绘制y数据。alpha=0.8指定图形所需的透明度级别
- 从
-
步骤 4 和步骤 5 对您来说非常熟悉。
执行代码后,您应该看到此处显示的图形:
多边形图
在本秘籍中,我们将学习如何绘制多边形图。 它类似于折线图,但在折线下填充。 在此示例中,我们还将使用相同的电池销售数据。
准备
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
from matplotlib.ticker import MultipleLocator
操作步骤
以下是编码逻辑的步骤:
- 定义用于 3D 绘图的图形和轴域:
fig = plt.figure(figsize=(10,6))
ax = fig.add_subplot(111, projection='3d')
- 准备 x,y 和 z 轴的数据:
## Years for which we have battery sales data
x = [2011, 2012, 2013, 2014, 2015]
## Repeat X, 5 times to represent each of the 5 battery ratings
X = x * 5
## List of Battery ratings
battery_ratings = ['7Ah', '35Ah', '40Ah', '135Ah', '150Ah']
## Number of units sold each year, each rating. e.g. 75 units of 7Ah(0) batteries,
## 144 units of 35Ah(1) batteries sold in 2011
Y = np.array([[75, 144, 114, 102, 108],
[90, 126, 102, 84, 126],
[96, 114, 75, 105, 135],
[105, 90, 175, 90, 75],
[90, 75, 135, 75, 90]])
## Represent battery rating in numeric codes
yticks = [0, 1, 2, 3, 4]
## Use different color for each of the battery ratings
colors = ['r', 'g', 'b', 'y', 'm']
- 准备要绘制的多边形的顶点:
vertices = []
for i in np.arange(0, 25, 5):
vertices.append([(xs[i], 0.)] + list(zip(xs[i:i+5], Y[:,int(i/5)])) + [(xs[i+4], 0.)])
- 绘制条形图:
poly = PolyCollection(vertices, facecolors=['r', 'g', 'b', 'y', 'm'], alpha=0.6)
ax.add_collection3d(poly, zs=yticks, zdir='y')
- 将 x 轴的主要刻度设置为
1的增量:
majorLocator = MultipleLocator(1)
ax.xaxis.set_major_locator(majorLocator)
- 设置 x,y 和 z 轴的限制:
ax.set_xlim(2011, 2015)
ax.set_ylim(-1,4)
ax.set_zlim(0,175)
- 设置 y 轴的刻度,并为 x,y 和 z 轴设置标签:
ax.set_yticks(yticks)
ax.set_yticklabels(battery_ratings)
ax.set_xlabel('Year')
ax.set_ylabel('Battery Type')
ax.set_zlabel('Units Sold')
- 在屏幕上显示该图:
plt.show()
工作原理
这是代码的说明:
- 前两个步骤与前面的秘籍完全相同
vertices.append([(xs[i], 0.)] + list(zip(xs[i:i+5], Y[:,int(i/5)])) + [(xs[i+4], 0.)])创建给定电池额定值的顶点。for循环会为所有电池额定值创建此类顶点。(xs[i], 0)和(xs[i+4],0.)是在 x 轴上终止的端点,其中 y 坐标为零, x 坐标是序列中的第一个和最后一个点。 将这两个点相加即可完成围绕 x 轴的循环,以便可以绘制出填充的多边形。poly = PolyCollection(vertices, facecolors=['r', 'g', 'b', 'y', 'm'], alpha=0.6)定义了一个多边形的集合,它等于给定的顶点:facecolors=['r', 'g', 'b', 'y', 'm']定义用于填充每个电池额定值的多边形的颜色。alpha=0.6定义每个填充多边形的透明度级别。
ax.add_collection3d(poly, zs=yticks, zdir='y')将集合添加到轴域,这实际上是绘制集合图的图:zs=yticks将yticks设置为 z 轴zdir='y'交换 z 和 y 轴数据,以便y数据用于 z 轴,而Z数据用于 y 轴,就像我们在前面的秘籍中所做的一样。
majorLocator = MultipleLocator(1)以 1 为步长定义majorLocator,ax.xaxis.set_major_locator(majorLocator)将其应用于 x 轴,以便不绘制和浮点数的年份。ax.set_xlim(2011, 2015),ax.set_ylim(-1,4)和ax.set_zlim(0,175)应用 x,y 和 z 轴的上限和下限。 这里需要这些来显示图形,因为此处的多边形和补丁是浮动对象,pyplot不知道使用的默认限制,这与所有其他情况不同,其中它会根据源数据中的数据点来确定限制。- 您已经熟悉了最后两个步骤。
在运行前面的代码时,您应该在屏幕上看到以下图形:
更多
对于前面的示例,我们使用了PolyCollection。 Matplotlib 中还有两个其他选项,LineCollection和PatchCollection。
等高线图
我们在第 2 章和“基本绘图入门”中学习了如何绘制 2D 等高线图。 在这里,我们将学习如何在 3D 模式下绘制它。 我们将使用与之前相同的数据,以便我们可以看到 2D 和 3D 可视化之间的差异。
准备
导入所需的库:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import cm
操作步骤
以下是创建所需图的步骤:
- 定义用于 3D 绘图的图形和轴域:
fig = plt.figure(figsize=(10,8))
ax = fig.gca(projection='3d')
- 加载
Loss,theta1和theta2变量的数据:
## Read Loss, theta0 and theta1 values
Loss = pd.read_excel('Loss.xlsx')
theta0_vals = pd.read_excel('theta0.xlsx')
theta1_vals = pd.read_excel('theta1.xlsx')
- 使用
np.meshgrid准备X和Y坐标:
X, Y = np.meshgrid(theta0_vals, theta1_vals)
- 绘制
contour图:
## Plot contour curves
cset = ax.contour(X, Y, Loss, np.logspace(-2,3,100), cmap=cm.coolwarm)
- 绘制颜色条:
fig.colorbar(cset, shrink=0.5, aspect=5)
- 设置标签:
ax.set_xlabel('theta0')
ax.set_ylabel('theta1')
ax.set_zlabel('Loss')
- 在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
- 前两个步骤是不言自明的。
X, Y = np.meshgrid(theta0_vals, theta1_vals)为theta0和theta1变量创建 x 和 y 坐标。 请参见第 2 章,“基本绘图入门”,以获得有关meshgrid的详细说明。cset = ax.contour(X, Y, Loss, np.logspace(-2,3,100), cmap=cm.coolwarm)绘制等高线图。 它为X和Y的各种值绘制,Loss变量的轮廓。 每个轮廓具有Loss(z 轴)的固定值,因此轮廓沿 z 轴垂直放置,而值最低的轮廓位于底部:np.logspace(-2,3,100)指定要绘制轮廓的损耗值范围。 它们的对数空间范围为 -2(线性范围为 0.01)至 +3(线性范围为 1000),并在此范围内均等间隔地采集 100 个样本。cmap=cm.coolwarm指定将coolwarm颜色表用于轮廓的可视化。
- 我们还绘制了 2D 中每个轮廓的损耗实际值,但 3D 并没有实现。
fig.colorbar(cset, shrink=0.5, aspect=5)设置颜色条,以显示与 , 指定的颜色表不同的颜色的轮廓:shrink=0.5指定颜色条大小从默认大小开始的缩小量。aspect=5在颜色条上指定数据的较大大小与较小大小的比率。
- 最后两个步骤是不言自明的。
运行前面的代码后,您应该在屏幕上看到下图:
更多
填充轮廓图还有另一种选择,其中整个轮廓填充有和指定的颜色。 您只需要在plot语句中用contourf替换轮廓。
曲面图
在本秘籍中,我们将学习如何绘制曲面图。 通常用于在机器学习问题中可视化损失(误差)表面。 当误差面具有多个最小值时,有助于查看算法是否卡在任何局部最小值中。 我们将使用与,之前的轮廓图相同的数据。
准备
导入所需的库:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
操作步骤
以下是绘制曲面图的步骤:
- 定义图形和 3D 绘图轴域:
fig = plt.figure(figsize=(10,8))
ax = fig.gca(projection='3d')
- 读取曲面图的数据:
## Read Loss, theta0 and theta1 values
Loss = pd.read_excel('Loss.xlsx')
theta0_vals = pd.read_excel('theta0.xlsx')
theta1_vals = pd.read_excel('theta1.xlsx')
- 为
X和Y坐标使用theta0和theta1的值范围创建meshgrid:
X, Y = np.meshgrid(theta0_vals, theta1_vals)
- 绘制曲面图:
## Plot surface graph
surf = ax.plot_surface(X, Y, Loss, cmap='plasma')
- 在图中添加颜色条:
fig.colorbar(surf, shrink=0.5, aspect=5)
- 为图形设置标签:
ax.set_xlabel('theta0')
ax.set_ylabel('theta1')
ax.set_zlabel('Loss')
- 在屏幕上显示该图:
plt.show()
工作原理
除了步骤 4,其中所有步骤均与之前的轮廓图完全相同,在该步骤中,我们将ax.contour()替换为ax.plot_surface()。 我们还用plasma颜色表替换了coolwarm颜色表。 其他所有内容都与等高线图相同。
执行代码后,您应该在屏幕上看到下图:
线框图
在本秘籍中,我们将学习如何绘制线框图。 它类似于曲面图,其中和选项在每个方向上采样多个点以连接到曲面。 在这里,我们将实现一个动画的线框图。
准备
将交互式输出的设置为所需的后端:
import matplotlib
matplotlib.use('Qt5Agg')
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
操作步骤
以下是绘制线框图所涉及的步骤:
- 定义用于 3D 绘图的图形和轴域:
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111, projection='3d')
- 准备 x 和 y 坐标的数据:
x = np.linspace(-2, 2, 25)
y = np.linspace(-5, 5, 25)
X, Y = np.meshgrid(x, y)
- 设置, x,y 和 z 轴的标签:
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
- 为 z 轴设置限制,以使动画激活时,轴刻度不会保持变化:
ax.set_zlim(-4, 4)
- 通过将 z 轴数据设为
X,Y的函数,并使用变量phi从0至90度来绘制动画线框图:
wframe = None
for phi in np.linspace(0, 90, 100):
if wframe:
ax.collections.remove(wframe)
Z = np.cos(2 * np.pi * X + phi) * (1 - np.sqrt(X**2 + Y**2))
wframe = ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)
plt.pause(0.1)
- 在 Qt5 后端上显示图形:
plt.show()
工作原理
这是代码的说明:
- x 是从 -2 到 +2 的 25 个数字的列表,它们之间的间距相等; 同样,y 是从 -5 到 +5 的 25 个数字的列表, x 和 y 是 x 和 y 之间的网格。
ax.set_zlim(-4, 4)将的 z 轴限制设置为 -4 至 +4。 由于 z 是变量phi的函数,因此这些数据限制在 z 轴上保持变化。 为避免更改图上的限制,请将限制的最大边界设置为 -4 到 +4。wframe = None初始化wframe变量。for phi in np.linspace(0, 90, 100):是for循环,从 0 开始,然后以 100 个相等的步长一直到 90 度。if wframe:检查线框是否已经存在。 第一次不会出现 。 不会出现,因为我们没有初始化它。 随后,它将始终为真,因此在绘制新的线框之前,将使用ax.collections.remove(wframe)将其删除。Z = np.cos(2 * np.pi * X + phi) * (1 - np.sqrt(X**2 + Y**2))根据 x,y 和phi的函数计算Z值。wframe = ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)绘制线框图:rstride是连接点之前沿行跳过的点数。cstride是连接这些点之前沿列跳过的点数。
plt.pause(0.1)暂停 0.1 秒,然后绘制下一个线框。 这就是创建动画效果的原因。- 在这里,我们不需要使用
plt.draw()或任何其他等效函数来刷新图形。plot_wireframe会照顾好它。
运行代码后,在动画完成后,您应该看到下图:
三角曲面图
在本秘籍中,我们将学习如何绘制三角形曲面图。 它类似于曲面图,但是曲面将具有三角形连接。 我们将使用不同的数据绘制三个这样的图,并显示轴和不显示轴。
准备
导入所需的库:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
操作步骤
以下是绘制三角形曲面图的步骤:
- 准备三个不同图的数据:
## Make radii and angles arrays.
radii = np.linspace(0., 1.0, 16)
angles = np.linspace(0, 2*np.pi, 32)
## Repeat all angles for each radius.
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
## Convert polar (radii, angles) coords to cartesian (x, y) coords.
x = (radii*np.cos(angles)).flatten()
y = (radii*np.sin(angles)).flatten()
## Compute z to make the triangle surface.
z = np.tan(x**2 + y**2)
z1 = np.cos(x**2 + y**2)
z2 = np.cos(x**3 + y**3)
- 定义图:
fig = plt.figure(figsize=(12,6))
- 绘制第一个三角形曲面图:
ax1 = fig.add_subplot(131, projection='3d')
ax1.plot_trisurf(x, y, z, linewidth=0.5, cmap='viridis')
- 绘制第二个三角形曲面图:
ax2 = fig.add_subplot(132, projection='3d')
ax2.plot_trisurf(x, y, z1, linewidth=0.5, cmap='cool')
plt.axis('off')
- 绘制第三个三角形曲面图:
ax3 = fig.add_subplot(133, projection='3d')
ax3.plot_trisurf(x, y, z2, linewidth=0.5, color='c')
plt.axis('off')
- 在屏幕上显示该图:
plt.show()
工作原理
这是代码的说明:
np.linspace(0., 1.0, 16)将的 0 到 1 范围划分为 16 个相等的部分,因为半径定义了在 0 和 1 之间平均分布的半径数,类似地,角度定义了在 0 和2 * pi之间平均分布的角度数(360 度)。np.repeat(angles[..., np.newaxis], n_radii, axis=1),为每个半径重复角度数组,创建一个32 x 16的矩阵:np.newaxis为每个半径创建一个附加大小。axis=1指定应将每个新维度添加为一列。
x = (radii*np.cos(angles)).flatten()使用极坐标在笛卡尔坐标系中创建 x 坐标。y = (radii*np.sin(angles)).flatten()使用极坐标在笛卡尔坐标系中创建 x 坐标。z = np.tan(x**2 + y**2)计算plot1的 z 坐标。z1 = np.cos(x**2 + y**2)计算plot2的 z 坐标。z2 = np.cos(x**3 + y**3)计算plot3的 z 坐标。fig = plt.figure(figsize=(12,6))定义并实例化该图形。ax1 = fig.add_subplot(131, projection='3d')定义了第一个轴域,ax1.plot_trisurf(x, y, z, linewidth=0.5, cmap='viridis')绘制了第一张图。 指定的色表是'viridis'。ax2 = fig.add_subplot(132, projection='3d')定义第二个轴域,ax2.plot_trisurf(x, y, z1, linewidth=0.5, cmap='cool')绘制第二个图。 指定的色表是cool。plt.axis('off')指定不显示绘图上的轴。ax3 = fig.add_subplot(133, projection='3d')定义了第三个轴域。ax3.plot_trisurf(x, y, z2, linewidth=0.5, color='c')绘制了第三个图。 我们使用单色代替该颜色表,并再次关闭轴。
执行代码后,您应该在屏幕上看到三个图形的图形:
在 3D 模式下绘制 2D 数据
在本秘籍中,我们将学习如何在 3D 模式下绘制 2D 数据。 我们将根据原因码将产品缺陷绘制为条形图,将累积缺陷绘制为线形图。 我们将在 x 轴,z 轴和 y 轴上的累积缺陷百分比。 在 2D 空间中,有两个 y 轴,其中一个具有条形图的比例,另一个具有折线图的比例。
准备
导入所需的库:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
操作步骤
以下是绘制和所需 3D 图的步骤:
- 定义用于 3D 绘图的图形和轴域:
fig = plt.figure(figsize=(10,6))
ax = fig.add_subplot(111, projection='3d')
- 定义条形图的数据并绘制:
x = [0, 1, 2, 3, 4, 5]
y = [19, 12, 6, 4, 3, 2]
ax.bar(x, y, zs=0, zdir='y', label='Number of Defects in (X,Z)')
- 为累积缺陷图定义的数据并绘制:
x = [0, 1, 2, 3, 4, 5]
y = [41, 67, 80, 89, 96, 100]
ax.plot(x, y, zs=0, zdir='z', color='g', lw=5, label='Cumulative Defects in (X,Y)')
- 设置 y 和 z 轴的限制:
ax.set_ylim(0,100)
ax.set_zlim(0,20)
- 为 x,y 和 z 轴设置标签,并设置图例:
ax.set_xlabel('Defect Reason Code')
ax.set_ylabel('Cumulative %of defects')
ax.set_zlabel('Number of Defects')
ax.legend(loc='best')
- 在屏幕上显示图:
plt.show()
工作原理
这是代码的说明:
x = [0, 1, 2, 3, 4, 5]是产品缺陷原因代码的列表。y = [19, 12, 6, 4, 3, 2]是按原因代码列出的缺陷计数。ax.bar(x, y, zs=0, zdir='y', label='Number of Defects in (X,Z)')绘制条形图:- 缺陷原因代码在 x 轴上,缺陷数量在 z 轴上。
zdir='y'交换 y 和 z 轴,以便在 z 轴域上绘制y数据。 在 y 轴域上绘制z数据,在这种情况下为零。- 指定的标签将显示在图例中。
y = [41, 67, 80, 89, 96, 100]是累积缺陷占总数百分比的列表。ax.plot(x, y, zs=0, zdir='z', color='g', lw=5, label='Cumulative Defects in (X,Y)')绘制线形图:- 缺陷原因代码在 x 轴上,累积缺陷在 y 轴上。
zdir='z'指定在上将z数据绘制在 z 轴上,在此情况下,轴由zs=0指定为零。color='g'指定和线形图应为绿色。lw=5指定图的线宽应为五个单位。- 标签将显示在图例上。
ax.set_ylim(0,100)设置 y 轴的上限和下限,ax.set_zlim(0,20)设置 z 轴的下限和上限。ax.set_xlabel('Defect Reason Code')设置 x 轴的标签。ax.set_ylabel('Cumulative %of defects')设置 y 轴的标签。ax.set_zlabel('Number of Defects')设置 z 轴的标签。ax.legend(loc='best')指定自动为图例选择最佳位置。
运行代码后,您应该在屏幕上看到下图:
在 3D 中可视化 2D 中的线性不可分离数据
在本秘籍中,我们将学习如何可视化在 3D 中线性不可分离的 2D 数据。 这通常用于解释支持向量机算法的内部工作原理,该算法将较低维的数据带到较高维的空间,以便可以找到一个平面。将数据整齐地分离为各种群集。
我们将使用相同的数据绘制 2D 和 3D 图,以使其可视化效果更好。
准备
导入所需的库:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
操作步骤
这是绘制和所需图形的步骤:
- 将数据从 Excel 文件读取到列表中:
## Read the Data, two product test scores, and result 1 means accepted and 0 means rejected
scores_data = pd.read_csv('test_scores_results.txt',header=None)
- 创建一个 Pandas 数据帧可以轻松地将数据分为不同的类别:
## Add columns labels to the data
columns = ['Test1_Score', 'Test2_Score', 'Accepted']
scores_data = np.array(scores_data)
df = pd.DataFrame(data=scores_data, columns=columns)
- 将数据分为
accepted和rejected类别:
df_accepted = df[(df['Accepted'] == 1.0)]
df_rejected = df[(df['Accepted'] == 0.0)]
- 将数据分为
accepted和rejected类别的 x 和 y 坐标:
accepted_score1 = np.array(df_accepted)[:,0]
accepted_score2 = np.array(df_accepted)[:,1]
rejected_score1 = np.array(df_rejected)[:,0]
rejected_score2 = np.array(df_rejected)[:,1]
- 定义并实例化图形:
fig = plt.figure(figsize=(12,8))
- 定义 2D 绘图的轴域并绘制
accepted和rejected数据点:
ax = fig.add_subplot(121)
ax.plot(accepted_score1, accepted_score2, 'gD', label='Accepted')
ax.plot(rejected_score1, rejected_score2, 'ro', label='rejected')
- 绘制 2D 图的标签和图例:
plt.xlabel('Test1 Score')
plt.ylabel('Test2 Score')
plt.legend(loc='best')
- 定义 3D 绘图的轴域:
ax = fig.add_subplot(122, projection='3d')
- 将接受和拒绝的数据点绘制为散点图:
ax.scatter(accepted_score1, accepted_score2, zs=-0.75, zdir='z', s=50, color='g',
marker='D', label='Accepted')
ax.scatter(rejected_score1, rejected_score2, zs=0.75, zdir='y', s=50, color='r',
marker='o', label='rejected')
- 为 3D 图设置标签,限制和图例:
ax.set_xlabel('Test1 Score')
ax.set_ylabel('Test2 Score')
ax.set_zlabel('Test2 Score')
ax.set_zlim(-1, 1)
ax.legend(loc='best')
- 在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
scores_data = pd.read_csv('test_scores_results.txt',header=None)从 Excel 文件的中读取数据,该文件没有标题。 它具有测试 1 和测试 2 得分,rejected状态为0,accepted状态为1。scores_data = np.array(scores_data)将scores_data转换为 NumPy 数组。df = pd.DataFrame(data=scores_data, columns=columns)使用scores_data数组和列名列表创建pandas数据帧df。df_accepted = df[(df['Accepted'] == 1.0)]使用test1和test2得分为accepted数据创建df_accepted数据帧。df_rejected = df[(df['Accepted'] == 0.0)]使用test1和test2得分为rejected数据创建df_rejected数据帧。accepted_score1 = np.array(df_accepted)[:,0]和accepted_score2 = np.array(df_accepted)[:,1]是accepted类别的 x 和 y 坐标。rejected_score1 = np.array(df_rejected)[:,0]和rejected_score2 = np.array(df_rejected)[:,1]是rejected类别的 x 和 y 坐标。ax.plot(accepted_score1, accepted_score2, 'gD', label='Accepted')绘制二维图,其中accepted类别点为绿色散点图,并带有菱形标记。 由于未提供线型参数,因此将其视为散点图。ax.plot(rejected_score1, rejected_score2, 'ro', label='rejected')将,rejected类别点绘制为红色的散点图,并带有一个圆形标记。 由于未提供线型参数,因此将其视为散点图。ax.scatter(accepted_score1, accepted_score2, zs=-0.75, zdir='z', s=50, color='g', marker='D', label='Accepted')在 xy 平面上绘制 3D 散点图,其中accepted类的z = -0.75。ax.scatter(rejected_score1, rejected_score2, zs=0.75, zdir='y', s=50, color='r', marker='o', label='rejected')在 xy 平面上绘制 3D 散点图,其中rejected类别的z = 0.75。- 其余的语句是不言自明的。
运行代码后,您应该在屏幕上看到下图:
词嵌入
在第 7 章,“嵌入文本和表达式”中,我们学习了如何在 2D 空间中绘制单词嵌入。 在这里,我们将学习如何在 3D 空间中绘制相同的单词嵌入。 要创建所需数据,我们将必须运行具有三个分量的t-SNE算法以生成 x,y 和 z 坐标。 我们将使用此输出来绘制图形。
准备
导入所需的库:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import pickle
操作步骤
以下是绘制单词嵌入图所涉及的步骤:
- 使用
pickle加载所需的数据:
threed_embeddings = pickle.load(open('threed_embeddings','rb'))
reverse_dictionary = pickle.load(open('word_reverse_dictionary',
'rb'))
- 创建用于 3D 绘图的图形和轴域:
fig = plt.figure(figsize=(20,20))
ax = fig.gca(projection='3d')
- 为每个
400最高字词绘制带有文本标注的散点图:
num_points = 400
words = [reverse_dictionary[i] for i in range(1, num_points+1)]
for i, label in enumerate(words):
x, y, z = threed_embeddings[i,:]
ax.scatter(x, y, z)
ax.text(x, y, z, label, ha='right', va='bottom')
- 设置 x,y 和 z 轴的限制和标签:
ax.set_xlim(-800,400)
ax.set_ylim(-200,800)
ax.set_zlim(-800,400)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
- 在屏幕上显示该图:
plt.show()
工作原理
它的工作原理与第 7 章“嵌入文本和表达式”中解释的 2D 等价物类似,不同之处在于输入文件具有三个组成部分,它们映射到三个维度 x,y 和 z。
运行代码后,您应该在屏幕上看到下图:
在这里,与 2D 等价物相比,相似的词看起来很少。 例如,数字 1、2、3、4、5 等看起来更远,而在 2D 中它们看起来像是一个不错的簇。 但是,它们仍然相对在一起。
十一、使用axisartist工具包
在本章中,我们将通过以下秘籍学习如何使用axisartist工具包的各种功能:
- 了解
AxisArtist中的属性 - 在矩形框中定义曲线网格
- 在矩形框中定义极坐标轴域
- 将浮动轴用于矩形图
- 使用浮动轴创建极坐标轴域
- 在浮动极坐标轴域上绘制行星系统数据
介绍
开发axisartist工具包的主要动机是支持曲线网格,例如用于在天文学中绘制行星系统的网格。 它有助于绘制在直角轴域和极坐标轴域上均具有弯曲轴域的图形,还可以帮助绘制具有浮动轴的图形。
axisartist是使用自 Matplotlib 主Axes类派生的自定义Axes类,其中每个轴(左,下,上和右)由单独的艺术家管理。 由于ax.axis的作用类似于字典,因此ax.axis["left"],ax.axis["bottom"],ax.axis["top"]和ax.axis["right"]可以访问它们。 我们还可以根据需要定义其他轴。
了解axisartist中的属性
在本秘籍中,我们将学习如何使用AxisArtist的基本属性和属性,例如固定轴,浮动轴,标签和刻度。 在本秘籍中,我们将不会使用这些属性绘制任何图形。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import mpl_toolkits.axisartist as AxisArtist
操作步骤
以下是绘制所需图形的步骤:
- 定义图形和
AxisArtist参数,然后将其添加到图形中,如下所示:
fig = plt.figure()
ax = AxisArtist.Axes(fig, [0.1, 0.1, 0.8, 0.8])
fig.add_axes(ax)
- 使用以下命令将上轴和右轴设置为不可见,然后设置轴的标签:
ax.axis["right", "top"].set_visible(False)
ax.set_xlabel("X Axis")
ax.axis["bottom"].label.set_rotation(30)
ax.set_ylabel("Y Axis")
- 在
y=1处创建一个浮动轴,如下所示:
ax.axis["y=1"] = ax.new_floating_axis(nth_coord=0, value=1.0)
ax.axis["y=1"].label.set_text("floating X axis on top")
- 在
x=0.5处创建另一个浮动轴,如下所示:
ax.axis["x=0.5"] = ax.new_floating_axis(nth_coord=1, value=0.5)
ax.axis["x=0.5"].set_axis_direction("top")
ax.axis["x=0.5"].label.set_text("floating Y axis in the middle")
- 使用以下命令在右侧创建一个固定轴:
ax.axis["right"] = ax.new_fixed_axis(loc="right", offset=(20, 20))
ax.axis["right"].set_axis_direction("bottom")
ax.axis["right"].label.set_text("fixed Y axis on right")
- 将颜色属性分配给所有轴的刻度线,刻度线标签和标签属性,如下所示:
ax.axis["left", "bottom"].major_ticks.set_color("darkblue")
ax.axis["left", "bottom"].major_ticklabels.set_color("darkblue")
ax.axis["left", "bottom"].label.set_color("darkblue")
ax.axis["right", "y=1"].major_ticks.set_color("green")
ax.axis["right", "y=1"].major_ticklabels.set_color("green")
ax.axis["right", "y=1"].label.set_color("green")
- 如下设置刻度线对齐,填充和 x 和 y 轴限制:
ax.axis[:].major_ticks.set_tick_out(True)
ax.axis[:].label.set_pad(10)
ax.set_xlim(0,2)
ax.set_ylim(-1,2)
- 通过以下命令设置轴
y=1的属性:
ax.axis["x=0.5"].toggle(all=False, label=True)
ax.axis["x=0.5"].label.set_color("red")
- 设置图形的标题(在这里,我们使用了
AxisArtist Demo),最后,在屏幕上显示图形,如下所示:
ax.set_title('AxisArtist Demo', pad=50, loc='right')
plt.show()
工作原理
这是前面代码的解释:
fig = plt.figure()定义图形对象。ax = AxisArtist.Axes(fig, [0.1, 0.1, 0.8, 0.8])定义AxisArtist类在给定坐标处的轴,分别从左侧开始,一直到底部,宽度和高度。fig.add_axes(ax)将轴域对象添加到图形中。ax.axis["right", "top"].set_visible(False)将上轴和右轴(脊)设置为不可见。 您也可以分别为每个轴设置此设置。ax.set_xlabel("X Axis")将 x 轴的标签设置为"X Axis"。ax.axis["bottom"].label.set_rotation(30)将 x 轴标签逆时针旋转 30 度。ax.set_ylabel("Y Axis")将 y 轴标签的标签设置为"Y Axis"。ax.axis["y=1"] = ax.new_floating_axis(nth_coord=0, value=1.0)定义了一个新轴,如下所示:- 浮动轴的位置会随着在 x 或 y 轴上设置的限制而变化,因为它是在数据坐标系中以轴的固定值创建的。
nth_coord指定新轴是与 x 还是 y 轴对齐。 设置为 0 时,它平行于 x 轴; 如果为 1,则新轴将平行于 y 轴。value参数指定轴上的值; 该新轴将被创建。 在这种情况下,由于value=1.0参数在y=1中创建了它。"y=1"是为此新轴指定的名称,并用它保存在ax.axis字典中。
ax.axis["y=1"].label.set_text("floating X axis on top")设置新浮动轴的标签。ax.axis["x=0.5"] = ax.new_floating_axis(nth_coord=1, value=0.5)会再创建一个浮动轴,如下所示:nth_coord=1指定此新轴应平行于 Y 轴。value=0.5指定应在x=0.5处创建新的浮动轴。"x=0.5"是为此新轴指定的名称。
ax.axis["x=0.5"].set_axis_direction("top")指定应在轴的哪一侧显示刻度线,刻度标签和轴标签。top表示它们都应位于轴的顶部或左侧,这取决于它是否平行于 x 或 y 轴。ax.axis["x=0.5"].label.set_text("floating Y axis in the middle")设置新轴的标签。ax.axis["right"] = ax.new_fixed_axis(loc="right", offset=(20, 20))创建如下固定轴:- 固定轴是位置固定的轴,因为它是相对于给定的轴/轴线以指定的偏移量创建的。
loc="right"指定应在绘图的右侧创建新轴。offset=(20, 20)指定距默认右轴的磅数偏移(1 点 = 1/72 英寸),在这种情况下,该偏移量将变为不可见。 它在 x 轴(底部)上方 20 个点,在默认右轴的右侧 20 个点。
ax.axis["right"].set_axis_direction("bottom")指定刻度,刻度标签和轴标签应绘制在新轴的右侧(或当轴平行于 x 轴时显示在底部)。ax.axis["right"].label.set_text("fixed Y axis on right")设置新轴的标签。ax.axis["left", "bottom"].major_ticks.set_color("darkblue")为左侧(y)和底部(x)轴的主要刻度设置深蓝色。ax.axis["left", "bottom"].major_ticklabels.set_color("darkblue")将深蓝色设置为刻度标签的颜色。ax.axis["left", "bottom"].label.set_color("darkblue")将深蓝色设置为轴标签的颜色。ax.axis["right", "y=1"].major_ticks.set_color("green")为"right"和"y=1"轴的主要刻度线设置绿色。ax.axis["right", "y=1"].major_ticklabels.set_color("green")为刻度标签设置绿色。ax.axis["right", "y=1"].label.set_color("green")为轴标签设置绿色。ax.axis[:].major_ticks.set_tick_out(True)在刻度标签的同一侧设置刻度。 默认情况下,在axisartist类中,刻度和刻度标签位于轴的相对侧。 应当注意,默认情况下,在 Matplotlib 主轴域中,类,刻度和刻度标签被绘制在该轴的同一侧。axis[:]包含字典中的所有元素,这意味着所有轴-默认情况下为四个轴和三个新添加的轴。 当然,"top"和"right"默认轴设置为"invisible"状态,因此您看不到它们的刻度和刻度标签! 因此,此函数仅适用于所有可见轴。ax.axis[:].label.set_pad(10)再次针对所有可见轴在轴及其标签之间添加填充(以便没有重叠)。ax.set_xlim(0,2)设置 x 轴的最小和最大限制。ax.set_ylim(-1,2)设置 y 轴的最小和最大限制。ax.axis["x=0.5"].toggle(all=False, label=True)使刻度和刻度标签不可见,而轴x=0.5的轴标签可见:all=False使刻度,刻度标签和轴标签均不可见。 您也可以一次更改刻度,刻度标签和标签的设置,而不是一次全部更改。label=True使轴标签可见。- 我们为
set_axis_direction参数使用默认选项,即底部(与 y 轴平行的轴的右侧)。
ax.axis["x=0.5"].label.set_color("red")为轴x=0.5的轴标签设置红色。plt.show()在屏幕上显示图形。
执行上述代码后,您应该在屏幕上看到以下示意图:
新的浮动轴和固定轴的刻度与相应的主轴域的 x或 y 轴刻度相同。 Matplotlib 当前不为这些新轴中的每一个支持不同的比例。 Matplotlib 3.0 版有望消除此限制。
在矩形框中定义曲线网格
在本秘籍中,我们将学习如何在使用笛卡尔坐标系的矩形轴域内创建具有自己的坐标系的曲线网格。 我们将在曲线坐标表示的两个点之间绘制一条简单的线形图。
这本质上是一个自定义开发的曲线坐标系,为此,我们必须定义从曲线坐标到笛卡尔坐标并以相反方向映射的函数。 在后续秘籍中,我们将学习axistartist类提供的预定义转换。
准备
您需要使用以下或命令导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axisartist import Subplot
from mpl_toolkits.axisartist.grid_helper_curvelinear import GridHelperCurveLinear
操作步骤
以下是绘制所需图形的步骤:
- 首先,将图形定义如下:
fig = plt.figure(1, figsize=(7, 4))
- 接下来,定义转换函数以将曲线坐标转换为直线坐标:
## Transformation Function to convert curvilinear coordinates to rectilinear coordinates
def curv2rect_tr(x, y):
x, y = np.asarray(x), np.asarray(y)
return x, y - x
- 定义转换函数以将直线坐标转换为曲线坐标:
## Transformation Function to convert rectilinear coordinates to curvilinear coordinates
def rect2curv_tr(x, y):
x, y = np.asarray(x), np.asarray(y)
return x, y + x
- 定义
grid_helper函数,该函数负责在具有直线坐标的矩形轴域上绘制具有曲线坐标的网格线。 它以变换函数为输入,并使用它们绘制网格线:
grid_helper = GridHelperCurveLinear((curv2rect_tr, rect2curv_tr))
- 使用上一步中定义的网格助手函数来定义轴域:
ax = Subplot(fig, 1, 1, 1, grid_helper=grid_helper)
- 将刚刚定义的轴域添加到图中:
fig.add_subplot(ax)
- 在曲线坐标中定义两个点,并将它们转换为等效的直线坐标:
x, y = curv2rect_tr([2.0, 8.0], [4.0, 16.0])
- 使用直线坐标绘制线形图,如下所示:
ax.plot(x, y, linewidth=2.0, color='g')
- 设置长宽比和 x 和 y 轴限制的值:
ax.set_aspect(1.)
ax.set_xlim(0, 15.)
ax.set_ylim(0, 15.)
- 使用浮动轴方法在曲线坐标中创建 x 和 y 轴,如下所示:
ax.axis["y"] = ax.new_floating_axis(nth_coord=0, value=4.0)
ax.axis["y"].set_ticklabel_direction('+')
ax.axis["x"] = ax.new_floating_axis(1, 9.0)
ax.axis["x"].set_ticklabel_direction('-')
- 打开背景网格:
ax.grid(True, zorder=0)
- 打印点
A,B,C和D代表 x 和 y 轴,曲线坐标中的点绘制为折线图:
ax.text(-1.5, 8.5, 'A', size=25, weight=50, color='b')
ax.text(8.5, -1.5, 'B', size=25, weight=50, color='b')
ax.text(3.5, -1.5, 'C', size=25, weight=50, color='b')
ax.text(3.5, 15, 'D', size=25, weight=50, color='b')
ax.text(2.0, 1.5, '(2.0, 4.0)', weight='bold', color='b')
ax.text(7.5, 8.5, '(8.0, 16.0)', weight='bold', color='b')
- 最后,使用以下命令在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
def curv2rect_tr(x, y)定义了将曲线坐标转换为直线坐标的函数。 它在新坐标中保留 x,但直线坐标中的 y 定义为y-x:x, y = np.asarray(x), np.asarray(y)将输入参数x和y重新定义为 NumPy 数组。- 将曲线坐标映射到直线坐标,直线系统的
x = x(两个系统中的值相同),直线系统中的y等于曲线系统中的y-x。
def rect2curv_tr(x, y)定义将直线坐标转换为曲线坐标的函数。 它是curv2rect函数的反函数。grid_helper = GridHelperCurveLinear((curv2rect_tr, rect2curv_tr))定义了一个辅助函数,它使用作为参数提供的转换函数在两个方向上绘制网格线。 因此,将使用新的浮动轴沿这些网格线设置其轴域。ax = Subplot(fig, 1, 1, 1, grid_helper=grid_helper)将轴域定义为子图,如下所示:fig是开头定义的图形对象。1,1,1与plt.subplot()表示法相似,并指定它是1 x 1网格内的第一个轴域。- 将先前定义的
grid_helper作为参数。
fig.add_subplot(ax)将轴域添加到图形中。x, y = curv2rect_tr([2.0, 8.0], [4.0, 16.0])在曲线坐标中获取(2.0, 4.0)和(8.0, 16,0)点,并将其转换为等效的直线坐标,分别为(2.0, 2.0)和(8.0, 8.0)。ax.plot(x, y, linewidth=2.0, color='g')绘制线宽为 2.0 点的绿色线形图。ax.set_aspect(1.)将长宽比设置为 1,这意味着 x 和 y 轴数据标尺都相等。ax.set_xlim(0, 15.)设置 x 轴的最小和最大限制,ax.set_ylim(0, 15.)设置 y 轴的限制。ax.axis["0"] = ax.new_floating_axis(nth_coord=0, value=4.0)在曲线坐标中为第一个坐标定义浮动轴,该坐标以 4.0 的值切割网格线。 在轴字典中将其命名为"0"轴。 该线由图中以蓝色突出显示的点 C 和 D 表示。ax.axis["0"].set_ticklabel_direction('+')指定刻度线标签应沿该轴的值递增方向放置在该轴的右侧。 如果为'-',则它们将放置在轴的左侧。 但是,默认情况下,刻度线的位置与刻度线标签的方向相反。ax.axis["1"] = ax.new_floating_axis(1, 9.0)定义第二条浮动轴,该第二条浮动轴在 X 轴上的值为 9.0。 在轴字典中将其命名为"1"。 该线在图中由以蓝色突出显示的点 A 和 B 表示。ax.axis["1"].set_ticklabel_direction('-')指定刻度标签应按递增顺序放置在轴的左侧。 在这种情况下,轴向下(从 0 到 8)增加,因此该方向的左侧在直线上方! 因此,刻度线标签位于行上方,而刻度线则位于行下方。ax.grid(True)显示网格线。ax.text(-1.5, 8.5, 'A', size=25, weight=50, color='b')绘制蓝色的点“ A”,大小为 25,权重为 50。类似地,B,C 和 D 点以及(2.0, 4.0)和(8.0, 16)坐标,用这些指定的属性绘制。plt.show()在屏幕上显示图形。
执行上述代码后,您应该在屏幕上看到以下示意图:
在矩形框中定义极坐标轴域
在前面的秘籍中,我们学习了定义自定义变换,并使用它来绘制曲线坐标中的曲线网格线。 但是,它们都使用 x,y 坐标的笛卡尔坐标系。 在本秘籍中,我们将学习如何在矩形框中使用极坐标(角度和半径坐标)。 在本秘籍以及所有后续秘籍中,我们将使用 Matplotlib 提供的预构建转换。
准备
您需要使用以下或命令导入必需的库:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axisartist.grid_helper_curvelinear import GridHelperCurveLinear
import mpl_toolkits.axisartist.angle_helper as angle_helper
from matplotlib.projections import PolarAxes
from matplotlib.transforms import Affine2D
from mpl_toolkits.axisartist import SubplotHost, ParasiteAxesAuxTrans
import matplotlib.cbook as cbook
操作步骤
以下是绘制图形所需的步骤:
- 如下定义图:
fig = plt.figure(1, figsize=(7, 4))
- 定义转换函数,如下所示:
## PolarAxes.PolarTransform needs angle units as radian. However, we # plot the coordinate system in degrees for easier visualization
curv2rect_tr = Affine2D().scale(np.pi/180., 1.) +
PolarAxes.PolarTransform()
- 计算角度和半径的边界值,以绘制网格线:
##(25, 25) is the number of steps it takes from minimum limit to
maximum limit for x and y
## number of grid lines(circular for radius, diagonal for angle) will
be influenced by these steps
extreme_finder = angle_helper.ExtremeFinderCycle(25, 25,
lon_cycle=360,
lat_cycle=None,
lon_minmax=None,
lat_minmax=(0, 50))
- 定义角度的网格定位器:
## Determine grid values appropriate for the coordinate (degree,
minute, second).
grid_locator1 = angle_helper.LocatorDMS(18)
- 定义角度的刻度格式器:
## Use an appropriate formatter to show angle values in degree,
minute and second format.
tick_formatter1 = angle_helper.FormatterDMS()
- 定义半径的网格定位器:
grid_locator2 = MaxNLocator(12)
- 定义绘制网格的网格助手:
grid_helper = GridHelperCurveLinear(curv2rect_tr,
extreme_finder=extreme_finder,
grid_locator1=grid_locator1,
tick_formatter1=tick_formatter1,
grid_locator2=grid_locator2)
- 使用前面定义的图形和网格帮助器定义主轴域:
ax = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper)
- 使用以下命令使右轴和上轴的刻度标签可见:
ax.axis["right", "top"].major_ticklabels.set_visible(True)
- 将角度刻度线映射到右轴,将半径刻度线映射到底轴,如下所示:
ax.axis["right"].get_helper().nth_coord_ticks = 0
ax.axis["bottom"].get_helper().nth_coord_ticks = 1
- 使用以下命令将主轴域添加到图中:
fig.add_subplot(ax)
- 定义一个从属轴域并将其附加到主轴域上:
axp = ParasiteAxesAuxTrans(ax, curv2rect_tr, "equal")
ax.parasites.append(axp)
- 在从属轴域上绘制折线图:
intp = cbook.simple_linear_interpolation
axp.plot(intp(np.array([0, 75, 180, 300]), 100), intp(np.array([9.,
12., 16, 21]), 100),
linewidth=2.0, color='g')
- 在折线图上标注起点和终点:
axp.text(0,7.5, '.', color='r', size=50)
axp.text(3,9.5, 'A(0,9)', color='b', weight='bold')
axp.text(295, 20.5, '.', color='r', size=50)
axp.text(300,21, 'B(300,21)', color='b', weight='bold')
- 设置主轴域的长宽比和 x 和 y 限制:
ax.set_aspect(1.0)
ax.set_xlim(-20, 22)
ax.set_ylim(-25, 20)
- 将网格选项设置为
True以显示网格:
ax.grid(True)
- 最后,使用以下命令在屏幕上显示图形:
plt.show()
工作原理
以下是上述代码的说明:
curv2rect_tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform()定义主轴域和从属轴域之间的转换:PolarAxes.PolarTransform()需要以弧度为单位的角度; 因此,我们添加scale(np.pi/180., 1.)以方便度数和弧度之间的转换。Affine2D是两个轴域之间的线性变换。
extreme_finder = angle_helper.ExtremeFinderCycle()计算给定 X,Y 限制和此函数中设置的其他参数的角度和半径的边界值:(25, 25)是从为 x 和 y 设置的最小和最大限制开始执行的步数。- 网格线的数量(半径为圆形,角度为对角线)将受这些步骤的影响。
lon_cycle=360为角度设置一个周期限制。 由于我们需要极坐标轴域,因此我们将其设置为 360 度。lat_minmax=(0, 50)设置半径的最小值和最大值。
grid_locator1 = angle_helper.LocatorDMS(30)确定适合于角度坐标的网格值(度,分,秒):- 参数中的数字 30 指定应绘制 30 条网格线作为角度坐标,每条网格线将转换为 12 度(
360/30)。 但是,您看到的网格线每 10 度绘制一次。 - 网格线取决于三组参数,并将决定平衡所有三组参数的网格线的最佳位置:
- 给定 x 和 y 限制。
- 赋予
extreme_finder函数的各种参数。 - 在
grid_locator中指定的参数。
- 参数中的数字 30 指定应绘制 30 条网格线作为角度坐标,每条网格线将转换为 12 度(
tick_formatter1 = angle_helper.FormatterDMS()格式化角度刻度标签以显示度数。grid_locator2 = MaxNLocator(12)确定半径的网格值。 数字 12 指定要在绘图上绘制的圆形网格的数量。 在这种情况下,我们在绘图上看到了 12 条网格线。 但是,根据其他参数集,这也可能略有不同。grid_helper = GridHelperCurveLinear()绘制给定转换函数,网格定位器和格式器的网格线。ax = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper)使用先前创建的图形和网格帮助器对象定义主轴域。ax.axis["right", "top"].major_ticklabels.set_visible(True)使右和上轴刻度标签可见,默认情况下不可见。ax.axis["right"].get_helper().nth_coord_ticks = 0将右轴映射到角度坐标。 在极坐标中,第一个(0)坐标是一个角度,第二个(1)坐标是半径。fig.add_subplot(ax)将主轴域添加到图形中。axp = ParasiteAxesAuxTrans(ax, curv2rect_tr)使用定义的转换函数在主轴域上定义极坐标的从属轴域。ax.parasites.append(axp)将从属轴域添加到主轴域。intp = cbook.simple_linear_interpolation表示将线性插值应用于要在从属轴域上绘制的数据。axp.plot()将寄生轴域的四个点绘制为绿色的线形图,线宽为 2.0。 参数100指定从起点到终点移动时要采取的增量数,以便沿轨迹平滑过渡。axp.text()绘制红点并用折线起点和终点的坐标对其进行标注。ax.set_aspect(1.0)设置 x 和 y 坐标之间的长宽比。ax.set_xlim(-20, 22)和ax.set_ylim(-25, 20)指定绘制图形和图表的 x 和 y 坐标的下限和上限。ax.grid(True, zorder=0)设置网格线,zorder=0指定在绘制任何其他艺术家之前应绘制网格线。 如果我们不设置此项,您将看到网格线与绿色线形图重叠,因为先绘制线形图,然后再绘制网格线! 为了避免这种重叠,我们为网格线的绘制函数设置了zorder=0。
执行上述代码后,您应该在屏幕上看到以下示意图:
将浮动轴用于矩形图
在本秘籍中,我们将学习如何绘制浮动轴。 当我们必须设计一个复杂的仪表板应用时,这些功能很有用,在该应用中,我们可能必须以不同于标准水平或垂直方向的其他方向放置单个图形或绘图。
我们将绘制三个不同的图以演示浮动轴的各种功能。
准备
您需要使用以下或命令导入必需的库:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
import mpl_toolkits.axisartist.floating_axes as floating_axes
操作步骤
以下是绘制所有三个图形所需的步骤:
- 如下定义图:
fig = plt.figure(1, figsize=(14, 6))
- 如下准备数据:
month_num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
units_sold = [500, 600, 750, 900, 1100, 1050, 1000, 950, 800, 700,
550, 450]
- 定义转换函数,如下所示:
curv2rect_tr1 = Affine2D().scale(200, 1).rotate_deg(30)
- 如下定义网格助手函数:
grid_helper1 = floating_axes.GridHelperCurveLinear(curv2rect_tr1,
extremes=(0, 13, 0, 1400))
- 使用以下命令定义主轴域和从属轴域:
ax1 = floating_axes.FloatingSubplot(fig, 131,
grid_helper=grid_helper1)
fig.add_subplot(ax1)
axp1 = ax1.get_aux_axes(curv2rect_tr1)
- 使用以下参数绘制条形图:
bars = axp1.bar(month_num, units_sold)
for bar in bars:
height = bar.get_height()
axp1.text(bar.get_x() + bar.get_width()/2., 1.002*height,'%d' %
int(height),
ha='center', va='bottom', rotation=30)
- 将刻度线设置为与网格线正确对齐,并指定标题,如下所示:
grid_helper1.grid_finder.grid_locator1._nbins = 14 # X axis ticks
grid_helper1.grid_finder.grid_locator2._nbins = 5 # Y axis ticks
axp1.text(5, 1800, 'bar plot', rotation=30, size=15, weight='bold',
color='b')
- 对箱形图重复上述所有步骤,如下所示:
## Read data
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
data = [wine_quality['alcohol'], wine_quality['fixed acidity'], wine_quality['quality']]
## Define transformation function
curv2rect_tr2 = Affine2D().scale(4, 1).rotate_deg(-30)
## Define grid helper function
grid_helper2 = floating_axes.GridHelperCurveLinear(curv2rect_tr2, extremes=(0, 4, 0, 20))
## Define main axes
ax2 = floating_axes.FloatingSubplot(fig, 132, grid_helper=grid_helper2)
fig.add_subplot(ax2)
## Define parasite axes
axp2 = ax2.get_aux_axes(curv2rect_tr2)
## Plot boxplot
axp2.boxplot(data)
## Set the tick and grid lines
grid_helper2.grid_finder.grid_locator1._nbins = 4
grid_helper2.grid_finder.grid_locator2._nbins = 5
## Set title and labels
axp2.text(1, 21, 'box plot', rotation=-30, size=15, weight='bold', color='b')
ax2.axis["bottom"].label.set_text('X axis')
ax2.axis["bottom"].label.set_color('blue')
ax2.axis["left"].label.set_text('Y axis')
ax2.axis["left"].label.set_color('red')
- 同样,对正弦/余弦函数作图重复相同的步骤,如以下代码块所示:
## Prepare data, define transformation and grid helper functions,
main axes
x = np.linspace(0, 10, 100)
curv2rect_tr3 = Affine2D().scale(1, 1).rotate_deg(10)
grid_helper3 = floating_axes.GridHelperCurveLinear(curv2rect_tr3, extremes=(0, 10, -5, 5))
ax3 = floating_axes.FloatingSubplot(fig, 133, grid_helper=grid_helper3)
fig.add_subplot(ax3)
## Define parasite axes, plot sine and cosine graphs, set title,
legend and grid
axp3 = ax3.get_aux_axes(curv2rect_tr3)
axp3.plot(x, 5*np.sin(x), label='sine')
axp3.plot(x, 5*np.cos(x), label='cosine')
ax3.legend(bbox_to_anchor=(0.35, 0., 1.05, 1.0), borderaxespad=0)
ax3.set_title('Sine/Cosine waves')
ax3.grid()
grid_helper3.grid_finder.grid_locator1._nbins = 5
grid_helper3.grid_finder.grid_locator2._nbins = 5
## Set labels, ticks and ticklabel attributes
ax3.axis["bottom"].label.set_text('X axis')
ax3.axis["bottom"].label.set_color('green')
ax3.axis["bottom"].major_ticks.set_color("green")
ax3.axis["bottom"].major_ticklabels.set_color("green")
ax3.axis["left"].label.set_text('Y axis')
ax3.axis["left"].label.set_color('red')
ax3.axis["left"].major_ticks.set_color("red")
ax3.axis["left"].major_ticklabels.set_color("red")
ax3.axis["bottom", "left"].major_ticks.set_tick_out(True)
ax3.axis["top", "right"].major_ticks.set_visible(False)
- 使用以下命令设置图形的标题,并调整图形之间的间距:
plt.suptitle('Floating Axes Demo',size=20, weight='bold', color='g')
plt.tight_layout()
plt.show()
工作原理
这是前面代码的解释:
curv2rect_tr1 = Affine2D().scale(200, 1).rotate_deg(30)是转换函数,其工作原理如下:Affine2D是线性变换。scale(200,1)指定 x 和 y 轴之间的数据刻度。 这需要根据要在 x 和 y 轴域上绘制的数据范围进行设置。rotate_deg(30)指定将绘图逆时针旋转 30 度。
grid_helper1 = floating_axes.GridHelperCurveLinear(curv2rect_tr1, extremes=(0, 13, 0, 1400))定义网格线如下:curv2rect_tr1是之前定义的转换函数。extremes=(0,13,0,1400)定义 x 和 y 轴的上下限。 在此, x 轴的范围是 0 到 13, y 轴的范围是 0 到 1,400。 注意两个范围之间的差距! 这就是为什么我们在转换函数中为比例设置(200, 1)的原因。
ax1 = floating_axes.FloatingSubplot(fig, 131, grid_helper=grid_helper1)定义主轴域如下:131表示它是三个图的1 x 3网格中的第一个图。
fig.add_subplot(ax1)将主轴域添加到图形中。axp1 = ax1.get_aux_axes(curv2rect_tr1)定义条形图的从属轴域。bars = axp1.bar(month_num, units_sold)在从属轴域上绘制条形图。for bar in bars在每个小节上打印带有单位数量的文本。 这与我们先前学到的相同,增加了rotation=30,以使文本沿与浮动轴相同的角度定向。grid_helper1.grid_finder.grid_locator1._nbins = 14定义 x 轴的刻度数。grid_helper1.grid_finder.grid_locator2._nbins = 5定义 y 轴的刻度数。axp1.text(5, 1800, 'bar plot', rotation=30, size=15, weight='bold', color='b')绘制条形图的标题。 通常的set_title()方法在这里不起作用,因此我们使用text选项!curv2rect_tr2 = Affine2D().scale(4, 1).rotate_deg(-30)定义要在不同轴域上绘制的箱形图的变换函数,如下所示:- 在此,我们基于此图的 x 和 y 轴的数据使用
scale(4,1)。 - 我们使用
rotate_deg(-30)规定绘图的顺时针旋转 30 度。
- 在此,我们基于此图的 x 和 y 轴的数据使用
grid_helper2 = floating_axes.GridHelperCurveLinear(curv2rect_tr2, extremes=(0, 4, 0, 20))定义了箱形图的网格助手函数:extremes=(0, 4, 0, 20)指定 x 和 y 轴的上下限。
ax2 = floating_axes.FloatingSubplot(fig, 132, grid_helper=grid_helper2)定义用于绘制箱形图的第二个轴域:132指定它是1 x 3绘图网格上的第二个绘图。grid_helper=grid_helper2指定用于该绘图的网格助手函数。
axp2 = ax2.get_aux_axes(curv2rect_tr2)定义用于箱形图的从属轴域。axp2.boxplot(data)在从属轴域上绘制箱形图。grid_helper2.grid_finder.grid_locator1._nbins = 4设置 x 轴的刻度数。grid_helper2.grid_finder.grid_locator2._nbins = 5设置 y 轴的刻度数。axp2.text(1, 21, 'box plot', rotation=-30, size=15, weight='bold', color='b')打印与轴的 30 度方向对齐的箱形图的标题。x = np.linspace(0, 10, 100)是绘制正弦波和余弦波的数据,作为该图中的第三幅图。curv2rect_tr3 = Affine2D().scale(1, 1).rotate_deg(10)为第三个图定义了比例为 1:1 且方向为 10 度的变换函数。grid_helper3 = floating_axes.GridHelperCurveLinear(curv2rect_tr3, extremes=(0, 10, -5, 5))定义了第三幅图的网格函数, x 限制为 0 到 10, y 限制为 -5 到 +5。ax3 = floating_axes.FloatingSubplot(fig, 133, grid_helper=grid_helper3)定义了第三幅图的第三主轴域,其中133指定它是图中1 x 3幅图网格上的第三幅图。axp3 = ax3.get_aux_axes(curv2rect_tr3)定义了第三幅图的从属轴域。axp3.plot(x, 5*np.sin(x), label='sine')在从属轴域上绘制正弦波。axp3.plot(x, 5*np.cos(x), label='cosine')在相同的从属轴域上绘制余弦波。ax3.legend(bbox_to_anchor=(0.35, 0., 1.05, 1.0), borderaxespad=0)设置图例,但未与轴的方向对齐。ax3.set_title('Sine/Cosine waves')会再次打印标题,但不会正确对齐,因此最好使用text方法,就像我们对前两个图所做的那样。ax3.grid()绘制网格线。 这些将与轴的方向正确对齐,因为它们由网格辅助函数参数控制并指定了nbins参数。grid_helper3.grid_finder.grid_locator1._nbins = 5指定 x 轴上刻度线/网格线的数量。grid_helper3.grid_finder.grid_locator2._nbins = 5指定 y 轴上刻度线/网格线的数量。plt.suptitle('Floating Axes Demo',size=20, weight='bold', color='g')打印整个图形的标题。
执行上述代码后,您应该在屏幕上看到以下示意图:
使用浮动轴创建极坐标轴域
在第 2 章(基本绘图入门)中,我们学习了如何在定义轴域的同时使用pyplot的projection='polar'选项绘制极坐标图。 在本秘籍中,我们将学习如何使用浮动轴绘制极坐标图。
准备
您需要使用以下或命令导入必需的库:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
import mpl_toolkits.axisartist.floating_axes as floating_axes
from matplotlib.projections import PolarAxes
from mpl_toolkits.axisartist.grid_finder import (FixedLocator, MaxNLocator, DictFormatter)
操作步骤
以下是绘制绘图所需的步骤:
- 如下定义图:
fig = plt.figure(1, figsize=(8, 4))
- 定义转换函数,如下所示:
curv2rect_tr = PolarAxes.PolarTransform()
- 如下定义角度坐标的自定义刻度字典:
pi = np.pi
angle_ticks = [(0, r"$0$"), (.25*pi, r"$\frac{1}{4}\pi$"),
(.5*pi, r"$\frac{1}{2}\pi$"), (.75*pi, r"$\frac{3}
{4}\pi$"),
( pi, r"$\pi$"), (1.25*pi, r"$1.25\pi$"),
(1.5*pi, r"$1.5\pi$"), (1.75*pi, r"$1.75\pi$")]
- 根据角度和半径坐标为定义网格定位器和格式器:
grid_locator1 = FixedLocator([value for value, string in
angle_ticks])
tick_formatter1 = DictFormatter(dict(angle_ticks))
grid_locator2 = MaxNLocator(5)
- 定义网格助手函数,如下所示:
grid_helper = floating_axes.GridHelperCurveLinear(curv2rect_tr,
extremes=(2*pi, 0, 5, 0),
grid_locator1=grid_locator1,
grid_locator2=grid_locator2,
tick_formatter1=tick_formatter1,
tick_formatter2=None)
- 定义主轴域和从属轴域:
main_axes = floating_axes.FloatingSubplot(fig, 111,
grid_helper=grid_helper)
fig.add_subplot(main_axes)
parasite_ax = main_axes.get_aux_axes(curv2rect_tr)
- 接下来,在从属轴域上绘制极坐标图:
theta = np.arange(0., 2., 1./180.)*np.pi
parasite_ax.fill(theta, 5*np.cos(8*theta), color=(0.8,0.0,0.9), hatch='//', alpha=0.5)
- 将网格设置为绘图的标题,标题,并在屏幕上显示图形:
main_axes.grid(True, zorder=0)
main_axes.set_title('Polar Plot using Floating Axes', weight='bold', color='b', pad=50)
plt.show()
工作原理
以下是上述代码的说明:
curv2rect_tr = PolarAxes.PolarTransform()定义极坐标变换函数。angle_ticks是用于角度坐标的刻度的字典,其中包含角度的值及其相应的文本表示形式。grid_locator1 = FixedLocator([value for value, string in angle_ticks])为角度坐标定义了网格定位器。FixedLocator()定义了字典指定的固定位置的刻度/网格位置。tick_formatter1 = DictFormatter(dict(angle_ticks))格式化要显示的角度坐标值。grid_locator2 = MaxNLocator(5)指定半径坐标的网格定位器。 数字5表示在半径图上应该有 5 条网格线。grid_helper = floating_axes.GridHelperCurveLinear()定义网格助手函数。 对于两个坐标,它以相反的顺序使用限制,即上限,然后是下限。 我们使用了(2*pi, 0, 5, 0),这意味着角度的上限为2 * pi,下限为零。 同样,半径的上限为 5,下限为零。main_axes = floating_axes.FloatingSubplot(fig, 111, grid_helper=grid_helper)定义主轴域。parasite_ax = main_axes.get_aux_axes(curv2rect_tr)定义了从属轴域。parasite_ax.fill(theta, 5*np.cos(8*theta), color=(0.8,0.0,0.9), hatch='//', alpha=0.5)使用填充方法和阴影线绘制极坐标图。color=(0.8,0.0,0.9)是使用 RGB 通道组合的自定义颜色。main_axes.grid(True, zorder=0)将网格线设置为可见。 网格线将在主图之前绘制,因此它们位于主图的背景中。
执行上述代码后,您应该在屏幕上看到以下示意图:
在浮动极坐标轴域上绘制行星系统数据
在本秘籍中,我们将学习有关使用浮动轴在极坐标中绘制行星系统数据的信息。 我们将绘制两个具有不同限制和属性的图表,以展示多种可能性。 我们没有学习任何新功能或代码,只是在实际应用中应用,我们在前面的秘籍中学习的功能。
准备
您需要使用以下或命令导入必需的库:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
import mpl_toolkits.axisartist.floating_axes as floating_axes
from matplotlib.projections import PolarAxes
import mpl_toolkits.axisartist.angle_helper as angle_helper
from mpl_toolkits.axisartist.grid_finder import MaxNLocator
操作步骤
以下是绘制两个图所需的步骤:
- 固定种子以确保数据的可重复性:
np.random.seed(19681211)
- 如下定义图:
fig = plt.figure(1, figsize=(12, 6))
- 定义转换函数,网格定位器和格式器,如下所示:
curv2rect_tr1 = Affine2D().translate(-85, 5).scale(np.pi/180., 1.) + PolarAxes.PolarTransform()
grid_locator1 = angle_helper.LocatorDMS(10)
tick_formatter1 = angle_helper.FormatterDMS()
grid_locator2 = MaxNLocator(4)
- 如下设置角度和半径坐标的限制:
## Specify angle coordinate limits in degrees
langle, uangle = 120., 225.
## Specify radial coordinate limits in '1000 km
lradius, uradius = 8, 16
- 定义网格助手函数:
grid_helper1 = floating_axes.GridHelperCurveLinear(curv2rect_tr1,
extremes=(langle, uangle, lradius, uradius),
grid_locator1=grid_locator1,
grid_locator2=grid_locator2,
tick_formatter1=tick_formatter1,
tick_formatter2=None)
- 定义主轴域并将其添加到图中,如下所示:
main_axes1 = floating_axes.FloatingSubplot(fig, 121, grid_helper=grid_helper1)
fig.add_subplot(main_axes1)
- 定义一个函数来设置轴的各种属性,如下所示:
def set_axis_attr(axes, leftlabel, toplabel):
axes.axis["bottom"].toggle(all=False) # by default all are visible, this makes them all invisible
axes.axis["right"].toggle(all=False) # by default ticks are visible, so this will make them invisible
axes.axis["left"].set_axis_direction("bottom")
axes.axis["left"].label.set(text=leftlabel, color='blue')
# by default label and ticklabels are invisible, this will make them visible
axes.axis["top"].toggle(all=True)
axes.axis["top"].set_axis_direction("bottom")
axes.axis["top"].major_ticklabels.set_axis_direction("top")
axes.axis["top"].label.set_axis_direction("top")
axes.axis["top"].label.set(text=toplabel, color='blue')
axes.axis[:].major_ticks.set_tick_out(True)
- 调用上一步中定义的函数:
set_axis_attr(main_axes1, "left axis", "top axis")
- 接下来,如下定义从属轴域:
parasite_axes1 = main_axes1.get_aux_axes(curv2rect_tr1)
- 在从属轴域上绘制散点图和折线图:
theta = np.random.randint(langle, uangle, 25) # in degrees
radius = np.random.randint(lradius, uradius, 25)
parasite_axes1.scatter(theta, radius)
parasite_axes1.plot([135, 165, 195, 225], [8, 10, 12, 16],
color='r')
- 使用以下命令设置显示的网格线:
main_axes1.grid(True, zorder=0)
- 对第二个图重复步骤 2 到 10,为您提供以下内容:
curv2rect_tr2 = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform()
grid_locator3 = angle_helper.LocatorHMS(10)
tick_formatter3 = angle_helper.FormatterHMS()
grid_locator4 = MaxNLocator(5)
langle, uangle = 0., 135.
lradius, uradius = 0, 25
grid_helper2 = floating_axes.GridHelperCurveLinear(curv2rect_tr2,
extremes=(langle, uangle, lradius, uradius),
grid_locator1=grid_locator3,
grid_locator2=grid_locator4,
tick_formatter1=tick_formatter3,
tick_formatter2=None)
main_axes2 = floating_axes.FloatingSubplot(fig, 122, grid_helper=grid_helper2)
fig.add_subplot(main_axes2)
set_axis_attr(main_axes2, "Radius('1000KM)", "Angle(HMS)")
parasite_axes2 = main_axes2.get_aux_axes(curv2rect_tr2)
theta = np.random.randint(langle, uangle, 25) # in degrees
radius = np.random.randint(lradius, uradius, 25)
parasite_axes2.scatter(theta, radius)
parasite_axes2.plot([0, 45, 90, 135], [5, 15, 20, 25], color='r')
main_axes2.grid(True, zorder=0)
- 最后,设置图形的标题,并使用以下命令在屏幕上显示图形:
plt.suptitle('Planetary System Plots',size=20, weight='bold',
color='g')
plt.show()
工作原理
由于本秘籍中未引入任何新功能或语法,因此在此不再重复代码说明。 所有这些语句和功能已经在本章的早期秘籍中进行了说明。
唯一的区别是,与第一幅图相比,我们为第二幅图使用了不同的网格定位器和格式化程序。 第一个遵循度,分钟和秒(DMS)格式,而第二个遵循小时,分钟和秒(HMS)格式。 在两个图的上轴刻度标签中都可以看到相同的内容。
运行上述代码后,您应该在屏幕上看到以下图表: