【Matplotlib】pyplot的高级功能

【Matplotlib】pyplot的高级功能,第1张

【Matplotlib】pyplot的高级功能

文章目录

添加图例与注释

给图形添加图例

代码运行结果代码分析 显示坐标点

代码运行结果代码分析 设置图形标题及坐标轴

设置图形标题及坐标轴

代码运行结果代码分析 一次性绘制多条曲线

代码运行结果代码分析 添加网格线

代码运行结果代码分析 绘制多个子图

绘制两个子图

代码运行结果代码分析 Axes与Subplot的区别

添加图例与注释 给图形添加图例 代码
import numpy as np
import matplotlib.pyplot as plt
nbSamples = 128

x = np.linspace(-np.pi, np.pi, nbSamples)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, color='g', linewidth=4, linestyle='--', label=r'$y = sin(x)$')
plt.plot(x, y2, '*', markersize=8, markerfacecolor='r',
         markeredgecolor='k', label=r'$y = cos(x)$')

plt.legend(loc='best')
plt.show()

运行结果

代码分析

首先,在第09和第11行为曲线添加了标签属性,然后在第16行,通过设置plt.legend(loc=‘best’)使图例能够在画布的“最佳”位置显示,这里的“最佳”是由系统自动判别的,通常哪里留白较多,系统就将图例放到哪里,loc参数是location(位置)的简写,表示图例所在位置,通常默认为最佳位置。

当然,我们也可以自行指定图例位置,可供选择的参数有:

upper right(右上)upper left(左上)lower left(左下)lower right(右下)right(右边)center left(左中)center right(右中)lowercenter(中下)upper center(中上)center(中)等。

Matplotlib在绘图的过程中,可以为各个轴的标题(Label)、图像的标题(Title)、图形的图例(Legend)等元素添加LaTeX风格的公式。添加公式并不复杂,只要在LaTeX公式的文本前后各增加一个$符号,Matplotlib就可以自动进行解析。如代码第9行和第11行所示,公式前面通常添加字母r,它是raw(原始的)的首字母,表示后面的字符串(即LaTeX公式)以原始字符形式存在,不需要进行转义解析。例如,字符串r’n’就表示两个字符,一个是“”另一个是“n”。如果去掉字符串前面的标识r,’n’就被解析为一个字符,即换行符。

显示坐标点 代码
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 10, 1)  # 构造X轴坐标向量
y = 2 * x  # 构造Y轴坐标向量

for a, b in zip(x, y):
    plt.text(a, b, (a, b), ha='center', va='bottom', fontsize=10)

plt.plot(x, y, 'bo-')
plt.show()

运行结果

代码分析

在本例中,我们使用plt.text()函数给图形添加了文本注释,借此把点的坐标逐个标注到了图形当中。
在第08行代码中,plt.text(a,b,(a,b),ha='center', va='bottom', fontsize=10)的前两个参数表示要标注的X轴和Y轴的坐标位置。第三个参数表示标注的文本内容,我们在这里打算显示的是坐标点。
在图中,我们可以看到,坐标点文本压在所绘制的曲线上,如果想优化显示文本的位置,我们可以调整前两个参数的位置。例如,plt.text(a- 0.5,b,(a,b))就表示把文本的X坐标左移0.5个单位。ha、va分别是horizontal alignment(水平对齐)、vertical alignment(垂直对齐)的简写。ha可选的参数有’center’、‘right’、‘left’,va可选的参数有’center’、‘top’、‘bottom’、‘baseline’、‘center_baseline’。

设置图形标题及坐标轴

在某些情况下,我们需要给图形设置一个标题,修改坐标轴的刻度值,或关闭坐标轴显示等。这时,我们可以使用plt.title()函数来给图形设置标题,使用plt.xticks()函数设置X轴的刻度值,使用plt.yticks()函数设置Y轴刻度值,使用plt.xlim()函数、plt.ylim()函数分别设置X轴和Y轴的区间范围,使用plt.xlabel()函数、plt.ylabel()函数设置X轴和Y轴的名称。

设置图形标题及坐标轴 代码
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-5, 5, 0.05)
y1 = np.sin(x)
y2 = np.cos(x)

# 为在Matplotlib中显示中文,设置特殊字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.title("双曲线")

plt.ylim(-1.2, 1.2)
plt.xlim(-6, 6)
plt.xticks(ticks=np.arange(-1.5 * np.pi, 2 * np.pi, 0.5 * np.pi),
           labels=['$-\frac{3}{2}pi$', '$-pi$', '$-\frac{1}{2}pi$',
                   '0', '$\frac{1}{2}pi$', '$pi$', '$\frac{3}{2}pi$'])
plt.yticks(ticks=[-1, 0, 1])
plt.xlabel("X轴")
plt.ylabel("Y轴")

plt.plot(x, y1, 'r-', label='$y_1 = sin(x)$')
plt.plot(x, y2, 'b:', label='$y_2 = cos(x)$')

plt.legend(loc='best')
plt.show()

运行结果

代码分析

在代码第12行,我们使用plt.xlim()设置X轴的坐标范围为(-6, 6)。这里xlim表示X轴的限度(limit)。类似地,ylim表示Y轴的限度(limit)。代码第13行使用plt.ylim()设置Y坐标轴范围为(-1.2, 1.2)。接着,使用plt.xlabel()设置X坐标轴名称’X轴’,使用plt.ylabel设置Y坐标轴名称’Y轴’。
我们使用plt.xticks()(代码第14行~16行)设置X轴的刻度,使用plt.yticks()(代码17行)设置Y轴的刻度。xticks()、yticks()函数分别用于设置X轴和Y轴的刻度与标签。这两个函数都有相同的参数ticks和labels。其中ticks用于设置坐标轴的刻度值,labels用于设置坐标轴的标签值,标签中可以添加LaTeX公式。

一次性绘制多条曲线 代码
import matplotlib.pyplot as plt
import numpy as np

# 在(0,4)区间,以间隔0.2均匀分隔
data = np.arange(0, 4, 0.2)

# 分别使用红色的点划线、蓝色的方块和绿色的三角形来区分这三条曲线
plt.plot(data, data, 'r-.', data, data ** 2, 'bs', data, data ** 3, 'g^')
plt.savefig('mult_lines.png', dpi=600)

运行结果

代码分析

第一个小技巧就是前面所说的,我们可以一次性地绘制多条曲线,如代码第08代码按照顺序先后提供了三条线段的X轴数据、Y轴数据和线条样式,实际上实现了 y = x y=x y=x、 y = x 2 y=x^2 y=x2和 y = x 3 y=x^3 y=x3这三条曲线的绘制。
为了区分这三条曲线,要让它们在样式上有所不同,

例如第一条曲线的参数是“r-.”,其中“r”表示红色(red),“-.”是非常形象的点画线。显而易见的是,“--”表现虚线,读者可自行测试一下。第二条曲线的样式是“bs”,其中“b”表示的是颜色blue(蓝色),“s”表示图形为方形(square)。第三条曲线的原始设置是“g^”,其中“g”表示的是颜色green(绿色),第二个字符“^”表示图形是“三角形”.

第二个值得关注的小技巧是,如果我们不想在屏幕显示图形,而是想将显示结果另存为一张图片以备后用,就可以使用savefig()方法。在该方法中填写对应的存储路径和文件名(包括扩展名)即可。这个方法神奇的地方在于,它会根据文件名的扩展名不同,自动识别图片并将其存储为对应的格式。

在第09行代码中,参数dpi=600并不是必需的。只有当你觉得生成图片的分辨率“惨不目睹”时,设置这个参数才有必要,可以提高分辨率。这里dpi表示的含义是Dots Per Inch(每英寸点数,简称DPI),它是一个量度单位,用于衡量生成图片的每英寸像素数量。通常,DPI越大,图片的清晰度也就越高,但占据的比特数也越高,不利于网络传输,所以有时候我们为了网络传输质量和传输速度,会对DPI的大小做一个合理的权衡。

添加网格线 代码
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(0, 4, 0.2)

plt.plot(data, data, 'r-.', data, data ** 2, 'bs', data, data ** 3, 'g^')

plt.grid(b=True)
plt.savefig('mult_lines-grid.png', dpi=600)

运行结果

代码分析

本例中的核心代码是第07行中的grid()方法,其原型如下。

grid(b = None, which = u'major', axis = u'both', **kwargs)

grid()方法的参数解释如下。

b:布尔类型变量,取值为[True | False],表示是否为图形添加网格,默认为False,即不添加。which:取值为[‘major’ | ‘minor’ | ‘both’],表示使用大网格(‘major’)或小网格(‘minor’),或大网格里套小网格(‘both’),默认为’major’。axis:取值为[‘both’ | ‘x’ | ‘y’],表示在哪个轴添加网格线,可以是X轴、Y轴,或X轴和Y轴均添加,默认为’both’,即X轴和Y轴均添加网格线。 绘制多个子图

在前面的讨论中,每次我们都绘制一张图片,实际上,有时候我们需要将多个子图绘制在一起进行比较。这时需要利用绘制子图的方法subplot(),其函数原型大致如下。

subplot(nrows, ncols, plot_number)

上述方法的功能为,绘制nrows行ncols列第plot_number个子图。显然,在这种布局下,我们一共有nrows×ncols个子图,参数plot_number指明是第几个子图。

绘制两个子图 代码
import matplotlib.pyplot as plt
import numpy as np

def f(t):
    return np.exp(-t) * np.cos(2 * np.pi * t)

t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)

# 第一种绘制子图的方法
fig = plt.figure()  # 创建一个画布
sub_fig1 = fig.add_subplot(211)  # 创建一个子图
sub_fig1.grid(True)  # 添加网格线
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')

# 第二种绘制子图的方法
plt.subplot(2, 1, 2)
plt.plot(t2, np.cos(2 * np.pi * t2), 'r--')
plt.show()
运行结果

代码分析

在本例中,我们提供了两种绘制子图的方法,二者是等价的。
第一种方法的思路是,我们先构建一个画布(第11行),然后在该画布上利用add_subplot()方法添加一个子图,其参数的含义同subplot()方法。这里的“211”,表示的就是两行一列第一个子图。构造子图时,我们可以添加网格线。
需要特别注意的是第14行代码。实际上,第14行中的plot()绘制了两个图形。第一个是由蓝色(标记为b)的实心圆(标记为o)标记的,X轴的数据为t1(第07行),Y轴的数据由第04~05行的函数f(t1)构造。第二个图形为黑色(标记符号为k)的曲线,其中,X轴的数据为t2(第08行),Y轴数据由第04~05行的函数f(t2)构造。两个图形叠加在一起构成了点画线。

第二种方法就是利用subplot()方法,它是子模块pyplot下属的方法,用起来更加简单明了。此处绘制的是红色虚线,绘制函数是cos2πx。这里的π是用NumPy模块中的np.pi表示的。

Axes与Subplot的区别


在绘图时,Figure(画布)最大,它有点像绘制实体画所用的画板,例如代码fig=plt.figure()的意思就是创建一个空画布。
在画布里,我们可以创建各种子图。子图主要有两类:一类是规规矩矩、排列整齐的子图,叫作Subplot;另一类是可以不那么规则摆放的子图,叫作Axes。
把Figure想象成Windows *** 作系统的桌面,在桌面上会有各种图标(icon),如果图标是自动对齐到网格的,就称之为Subplot;如果图标是自由摆放的,甚至可以相互重叠的那种,就称之为Axes。但不管怎么摆放,Subplot和Axex本质上都是Figure内的子图。
但让我们比较困惑的是,在绘图时axis会出来捣乱。其实axis是地地道道的坐标轴。每个子图都有坐标轴。为了获得更好的可读性,每个坐标轴都可以配上标签(label)。例如,X轴有xlabel这个属性,Y轴有ylabel属性等。
可能Matplotlib的设计者认为,任何一个子图都要通过多个轴(axis)来呈现(二维图有两个轴,三维图有三个轴),众轴成图,所以就用“axis”的复数形式“Axes”表示子图。但切不可认为Axes是多个轴(axis)的意思,而应该在整体上把它视为一个在画布中可任意摆放的子图。下面,我们举例说明。

import matplotlib.pyplot as plt

# 生成一个没有子图(Axes)的画布
fig = plt.figure()
plt.show()

这样会没有图片显示出来。
如果没有子图,光有一个画布,是无法构成一个图形显示对象的。但是,如果我们有意识地添加子图,哪怕是一个空子图,它也构成了可显示的图形对象。

# 生成一个画布,其中有2*2分布均匀的子图
fig, axes_lst = plt.subplots(2, 2)
plt.show()

值得注意的是,plt.subplots()返回两个值,一个是Figure(画布),另一个就是Axes对象,此处命名为axes_lst。如前文所述,在这种场景下,Axes就是Subplot。

现在,我们有四个子图(Axes),那该如何区分它们呢?这个区分并不复杂,类似于NumPy的多维数组访问,ax_lst[0,0]就表示第0行第0列的子图(下标从0开始计数,下同),即左上角的图。类似地,ax_lst[0,1]就表示第0行第1列的子图,即右上角的图。以此类推。

如果我们知道这个区分方式,就可以“指哪打哪”了。比如说,我们仅仅想在右下角的子图上绘制特定图形,就可以如下 *** 作。

# 构造x轴和y轴数据
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
# 在第一行第一列的子图中绘图
axes_lst[1, 1].plot(x, y)
plt.show()


上述代码中的axes_lst[1, 1].plot(x, y)完全等价于pyplot模型下的如下两行代码。

我们想绘制一个大图中套小图的图形,即“图中图”,使用Axes就相对容易 *** 控一些,代码如下。

# 创建空画布
fig = plt.figure()

left1, bottom1, width1, height1 = 0.1, 0.1, 0.8, 0.8
# 在画布上添加一个子图
axes_1 = fig.add_axes([left1, bottom1, width1, height1])
axes_1.scatter(x, y)
axes_1.set_xlabel('x')
axes_1.set_ylabel('y')
axes_1.set_title('title')

left2, bottom2, width2, height2 = 0.6, 0.6, 0.25, 0.25
# 在画布上添加另外一个子图
axes_2 = fig.add_axes([left2, bottom2, width2, height2])
axes_2.plot(x, y)
axes_2.set_title('title inside')

plt.show()

在以上代码中,我们使用fig.add_axes([left, bottom, width, height])添加子图时,要事先确定子图在画布的位置,这时需要四个参数来定位:图左下角(即原点的左边坐标和底部坐标)的位置和图形大小(宽和高)。但需要注意的是,这四个值都用占整个Figure坐标系的百分比来表示,即都是小于1的小数

假设Figure的大小是10×10,对于上述代码的配置,我们绘制的大图起点(原点)就是坐标(1, 1),因为left=10*0.1=1,bottom=10 * 0.1=1。类似地,我们也很容易获知大图的width=8,height=8。对小图的计算也是类似的,不再赘述。从图中可以看出,我们同样可以对小图设置X轴和Y轴的标签及图形标题。

由上面的分析可知,用add_axes()方法生成子图灵活性更强,它完全可以实现add_subplot()方法的功能,且更容易控制子图的显示位置,甚至实现相互重叠的效果(参见以下代码)。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig = plt.figure()
axes_1 = fig.add_axes([0.1, 0.1, 0.5, 0.5])
axes_2 = fig.add_axes([0.2, 0.2, 0.5, 0.5])
axes_3 = fig.add_axes([0.3, 0.3, 0.5, 0.5])
axes_4 = fig.add_axes([0.4, 0.4, 0.5, 0.5])
axes_4.plot(x, y)

plt.show()

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5721254.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存