一直将matplotlib当做一个工具来用,因为没有了解到它的特性,所以一直学得不系统,导致用到的时候经常要查官方文档。这里翻译一个官方推荐的matplotlib的介绍文档。
猛戳进入原文链接
文档中包含的内容:
该博客只翻译123小节,下一篇博客介绍下面的
你可以点击图片上面的源代码超链接获取当前图形的代码。这些链接也是原英文文档的作者提供的。
matplotlib可能是最常用的2D绘图Python包了。它可以对Python中的数据进行快速的可视化,并以多种格式输出。接下来,我们将以互动的方式介绍matplotlib中的大多数情况
在matplotlib面向对象的绘图库中,pyplot是一个方便的接口。
在这一章,我们想在一个图中画一个cosine函数和一个sine函数。对于画图时的细节,我们先让它默认,然后再一步一步按自己的要求丰富figure,让它变得更visible。
首先,由sine函数和cosine函数获取数据:
import numpy as np
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
其中,np.linspace(...)
的意思是从- π π 到+ π π 均匀的取256个点(包括最后一个点- π π )。至此,C就是一个由256个点组成的cosine函数,而S是一个由256个点组成的sine函数。
为了方便起见,matplotlib给出了很多默认设置。 你几乎可以控制所有matplotlib中提供的属性值:figure大小和像素,line的宽度、颜色和样式,axes,axis和grid属性,文本和字体属性等等。尽管大多数情况下,matplotlib的默认值都足够好了,但在某些情况下,你可能还是想用自己的方式修饰这些属性。
源代码和结果如下所示:
import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C,S = np.cos(X), np.sin(X)
plt.plot(X,C)
plt.plot(X,S)
plt.show()
在下面的脚本中,我们初始化一些参数。下面修改的参数实际上与默认值是一样的,但你可以通过修改这些参数,观察结果图形的变化。
源代码和结果如下所示:
# 模块导入
import numpy as np
import matplotlib.pyplot as plt
# 创建一个8x6大小的figure,并设置每英寸80个像素点
plt.figure(figsize=(8, 6), dpi=80)
# 创建在1x1的位置创建一个subplot
plt.subplot(111)
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
# 绘制cosine函数,颜色是蓝色,line宽为1.0,line类型是实线
plt.plot(X, C, color='blue', linewidth=1.0, linestyle='-')
# 绘制sine函数,颜色是绿色,line宽为1.0,line类型是实线
plt.plot(X, S, color='green', linewidth=1.0, linestyle='-')
# 设置x轴和y轴范围
plt.xlim(-4.0, 4.0)
plt.ylim(-1.0, 1.0)
# 设置x轴下标和y轴下标
plt.xticks(np.linspace(-4, 4, 9, endpoint=True))
plt.yticks(np.linspace(-1, 1, 5, endpoint=True))
# 保存图片,每英寸72个点
# 如果此处报错,在当前路径下创建figures文件夹
# savefig("../figures/exercice_2.png", dpi=72)
# 在屏幕上显示结果
plt.show()
将cosine函数改成蓝色,sine函数改成红色,将它们的line加宽为2.5,同时也修改了figure的大小,使图形的比例看起来更好。
源代码和结果如下所示:
plt.figure(figsize=(10, 6), dpi=80)
plt.plot(X, C, color='blue', linewidth=2.5, linestype='-')
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")
改变了x轴和y轴的范围,让图形看起来既完整又紧致。
源代码:和结果如下所示
plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.ylim(C.min() * 1.1, C.max() * 1.1)
当前的坐标轴下标并不理想,因为它们没有标出我们感兴趣的点- π/2 π / 2 和+ π/2 π / 2 。
源代码和结果如下所示:
plt.xticks( [-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, +1])
坐标轴的下标的位置现在很理想,但是它的名字(也就是表现形式)不应该是3.142,最好是 π π 。注意matplotlib的坐标轴的下标包括位置(location)和名字(label)两部分。现在,我们利用latex来命名下标。
源代码和结果如下所示:
# r''是为了转义里面的转义字符\
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
plt.yticks([-1, 0, +1], [r'$-1$', r'$0$', r'$+1$'])
spines包括图片上下左右4条边界和它们的下标,就是正方形的4条边。它们可以被挪到任意的位置,现在,它们还在边界上。我们要把它们移到中间。首先,将上边界和右边界的颜色设置为none,就隐藏了。然后我们将下边界和左边界移动到数据空间的0处。
源代码和结果如下所示:
# plt.gca()获取当前ax
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
# set_position中的参数元组的第二个值可取-1,0,1分别代表相对‘data’的不同的位置
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))
legend就是如下图所示的东西。这个需要调整两点:一个是参数label,一个是plot命令plt.legend()
。
源代码和结果如下所示:
plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-", label="sine")
# frameon=True的话,右上角的声明会在一个框内
plt.legend(loc='upper left', frameon=False)
让我们来用plt.annotate()
命令来标记一些感兴趣的点。我们选了 2π/3 2 π / 3 点来标记它在sine和cosine函数上的值。首先,绘制一个点和虚线。然后我们用annotate命令添加文本和箭头上去。
源代码和结果如下所示:
t = 2*np.pi/3
plt.plot([t,t],[0,np.cos(t)], color ='blue', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.cos(t),], 50, color ='blue')
# 第一个参数s为要标记上去的文本
# 第二个参数xy为标记的位置,必须是可迭代对象(如tuple,list)
# 第三个对象xycoords表示xy的参考系
# 第四个对象xytext为标记文本相对标记位置的位置,必须是可迭代对象iterabl
# 第五个对象textcoords表示xytext的参考系
# 第六个对象fontsize为字体大小
# 第七个对象arrowprops为箭头样式
plt.annotate(r'$\sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$', xy=(t, np.sin(t)), xycoords='data', xytext=(+10, +30), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
plt.plot([t,t],[0,np.sin(t)], color ='red', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.sin(t),], 50, color ='red')
plt.annotate(r'$\cos(\frac{2\pi}{3})=-\frac{1}{2}$', xy=(t, np.cos(t)), xycoords='data', xytext=(-90, -50), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
labels现在被红线和蓝线挡住了。我们可以把label的字条调大,让红蓝线变成半透明的。
源代码和结果如下所示:
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(16)
label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))
到目前为止,我们使用的都是直接了当的单一figure和axes。这可以帮我们方便快速的绘图。此外,我们还可以使用figure,subplot和axes创造更多的布局。figure是matplotlib中面向用户的最大的界面,figure里面是subplots。subplot指定plots在figure中的位置,axes就是被指定位置后的的plots,这些都可以按照你的意愿来布局。我们之前的代码都没有声明它们。如果我们要调用plot,gca()
获取当前axes,gcf()
获取当前figure。如果没有当前figure,就创建一个并返回。
一个figure就是一个在GUI中名为“Figure#”的一个窗口,它的计数是从1开始的,跟普通的Python计数方式不同,而是MATLAB的计数风格。下面是几个定义figure外形的参数。
参数 | 默认值 | 描述 |
---|---|---|
num | 1 | figure编号 |
figsize | figure.figsize | figure长和宽 |
dpi | figure.dpi | 像素 |
facecolor | figure.facecolor | 背景颜色 |
edgecolor | figure.edgecolor | 边缘颜色 |
frameon | True | 边框有无 |
大多数情况下,figure都是使用默认值,只有num参数才会经常改动。
如果你是以GUI的形式工作,可以点击右上角的x关闭figure,也可以通过调用函数关闭figure,如plt.close()
。无参数表示关闭当前figure,有参数int表示关闭特定figure,还可以通过修改参数关闭所有figure。
figure对象和其他对象一样,可以通过set_
类型的函数修改参数。
subplot是用来布局plots的,需要指定(行、列、序号)。
点击获取源代码,效果图如下:
点击获取源代码,效果图如下:
点击获取源代码,效果图如下:
点击获取源代码,效果图如下:
Axes和subplots很像,但它可以布局在figure的任意位置。所以如果我们想把一个小plot放在一个大plot里面,应该采用Axes。
点击获取源代码,效果图如下:
点击获取源代码,效果图如下:
合适的ticks对于图片的绘制非常重要。matplotlib提供了一个完整的ticks配置系统,tick locators表明ticks应该处于什么位置;tick formatters可以提供要展示的tick名字。major ticks和minor ticks是相互独立的。因为没有位置信息,每一个默认的minor ticks是不显示的,它们只是一个空列表。
下面是不同的位置信息:
Class | Description |
---|---|
NullLocator | 没有ticks 图一 |
IndexLocator | 对每一个重要绘图点都设置一个tick 图二 |
FixedLocator | 灵活的ticks 图三 |
LinearLocator | 线性ticks 图四 |
MultipleLocator | 对每一个绘图点都设置一个tick 图五 |
AutoLocator | 选择不多于n个比较好的ticks 图六 |
LogLocator | log类型的ticks 图七 |
1.
2.
3.
4.
5.
6.
7.
所有这些定位器都从基类matplotlib.ticker.Locator派生。 你可以制作自己的定位器。 处理日期作为ticks可能是特别棘手的。 因此,matplotlib在matplotlib.dates中提供了特殊的定位器。