文章目录
欢迎关注公众号【Python开发实战】,免费领取Python学习电子书!
工具-matplotlib
使用matplotlib可以绘制出漂亮的图形。
子图
导入matplotlib
import matplotlib
import matplotlib.pyplot as plt
一个matplotlib图形可能包含多个子图。这些子图被组织在一个网格中。创建子图,只需要调用subplot()函数,并指定图中的行数和列数,以及要绘制的子图的索引(从1开始,然后从左到右,从上到下)。需要注意,pyplot会跟踪当前活跃的子图(可以通过调用plt.gcs()函数对它进行引用),因此当调用plot()函数时,会绘制活跃的子图。
import numpy as np
x = np.linspace(-1.4, 1.4, 30)
plt.subplot(2, 2, 1) # 2行 2列 第一个子图 = 左上角
plt.plot(x, x)
plt.subplot(2, 2, 2) # 2行 2列 第二个子图 = 右上角
plt.plot(x, x**2)
plt.subplot(2, 2, 3) # 2行 2列 第三个子图 = 左下角
plt.plot(x, x**3)
plt.subplot(2, 2, 4) # 2行 2列 第四个子图 = 右下角
plt.plot(x, x**4)
plt.show()
subplot(2, 2, 3)可以简写为subplot(223)。
创建跨越多个网格单元的子图也很容易。
plt.subplot(2, 2, 1) # 2行 2列 第一个子图 = 左上角
plt.plot(x, x)
plt.subplot(2, 2, 2) # 2行 2列 第二个子图 = 右上角
plt.plot(x, x**2)
plt.subplot(2, 1, 2) # 2行 1列 第二个子图 = 底部
plt.plot(x, x**3)
plt.show()
如果需要更复杂的子图定位,可以使用subplot2grid,而不是使用subplot。可以指定网格中的行数和列数,然后指定子图在网格中的位置,左上为(0,0),还可以指定子图跨越的行数或列数。
plt.subplot2grid((3, 3), (0, 0), rowspan=2, colspan=2)
plt.plot(x, x**2)
plt.subplot2grid((3, 3), (0, 2))
plt.plot(x, x**3)
plt.subplot2grid((3, 3), (1, 2), rowspan=2)
plt.plot(x, x**4)
plt.subplot2grid((3, 3), (2, 0), colspan=2)
plt.plot(x, x**5)
plt.show()
多个figure
也可以绘制多个图。每个图都可能包含一个或多个子图。默认情况下,matplotlib会自动创建figure(1)。切换figure时,pyplot会跟踪当前活跃的figure(可以通过调用plt.gcf()获得它的引用),当前活跃的figure的活跃子图将成为当前的子图。
plt.figure(1)
plt.subplot(211)
plt.plot(x, x**2)
plt.title('Square and Cube')
plt.subplot(212)
plt.plot(x, x**3)
plt.figure(2, figsize=(10, 5))
plt.subplot(121)
plt.plot(x, x**4)
plt.title('y = x**4')
plt.subplot(122)
plt.plot(x, x**5)
plt.title('y = x**5')
plt.figure(1) # 回到 figure 1, 当前的子图是 212 (bottom)
plt.plot(x, -x**3, 'r:')
plt.show()
pyplot的状态机:隐式和显式
到目前为止,已经使用pyplot的状态机来跟踪当前活跃的子图。每次调用plot()函数时,pyplot只会绘制在当前活跃的子图。它还有一些更神奇的功能,比如在调用plot()函数时,如果figure和子图不存在,会自动创建一个figure和一个子图。这在互动环境(如jupyter)中很方便。但在编写程序时,显式比隐式更好,因为显式代码通常更容易调试和维护。
pyplot允许完全忽略状态机,因此可以编写漂亮的显式代码。只需要嗲用subplot()函数,并使用figure对象和返回的axes对象列表。
x = np.linspace(-2, 2, 200)
fig1, (ax_top, ax_bottom) = plt.subplots(2, 1, sharex=True)
fig1.set_size_inches(10, 5)
line1, line2 = ax_top.plot(x, np.sin(3*x**2), 'r-', x, np.cos(5*x**2), 'b-')
line3 = ax_bottom.plot(x, np.sin(3*x), 'r-')
ax_top.grid(True)
fig2, ax = plt.subplots(1, 1)
ax.plot(x, x**2)
plt.show()
pylab vs pyplot vs matplotlib
pylab、pyplot和matplotlib之间的关系会存在一些混淆。很简单:
- matplotlib是完整的库,包含所有的内容,包括pylab和pyplot。
- pyplot提供了许多绘图工具,包括底层面向对象绘图库的状态机接口。pyplot和numpy在一个命名空间。
- pylab是一个方便的模块,用于导入matplotlib。可能你会发现许多实用pylab的示例,但是不推荐这么使用,因为显式导入好于隐式导入。