机器学习基础7--python画图库matplotlib(下)

第一篇我们讲了matplot画图的基本要素,第二篇讲matplot若干个常见的基础图的画图操作。最后一篇我们讲一下matplot画图中可能会用到的几个高级用法。

Subplot 多图合一

matplotlib 是可以组合许多的小图, 放在一张大图里面显示的. 使用到的方法叫作 subplot.

均匀分布

1
2
3
4
5
6
import matplotlib.pyplot as plt

plt.figure()
plt.subplot(2, 2, 1) # 创建小图,将整个图像窗口分为2行2列,当前位置为1
plt.plot([0, 1], [0, 1]) # 经过(0,1) (1, 1)画一条直线
plt.show()

将这四个区域都填满:

1
2
3
4
5
6
7
8
9
10
plt.figure()
plt.subplot(2, 2, 1) # 创建小图,将整个图像窗口分为2行2列,当前位置为1
plt.plot([0, 1], [0, 1])
plt.subplot(2, 2, 2) # 当前位置为2
plt.plot([0, 1], [0, 2])
plt.subplot(223) # 简写
plt.plot([0, 1], [0, 3])
plt.subplot(224)
plt.plot([0, 1], [0, 4])
plt.show()

非均匀分布

1
2
3
4
5
6
7
8
9
plt.subplot(2, 1, 1)  # 两行一列
plt.plot([0, 1], [0, 1])
plt.subplot(2, 3, 4) # 两行三列,当前位置是4(因为该命令执行后,第一行重新变成三列,所以当前位置3+1=4)
plt.plot([0, 1], [0, 2])
plt.subplot(235)
plt.plot([0, 1], [0, 3])
plt.subplot(236)
plt.plot([0, 1], [0, 4])
plt.show()

分格

subplot2grid()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import matplotlib.pyplot as plt

plt.figure() # 创建图像
ax1 = plt.subplot2grid((3, 3), # 三行三列
(0, 0), # 从第0行第0列开始作图
colspan=3 # 跨度为3,一整行
)
ax1.plot([1, 2], [1, 2]) # 画小图
ax1.set_title('ax1_title') # 设置小图的标题
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
ax4 = plt.subplot2grid((3, 3), (2, 0))

ax4.scatter([1, 2], [2, 2])
ax4.set_xlabel('ax4_x')
ax4.set_ylabel('ax4_y')

plt.show()

gridspec

导入matplotlib.gridspec模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

# 画布分为3x3
gs = gridspec.GridSpec(3, 3)
# 第0行,跨整行
ax6 = plt.subplot(gs[0, :])
ax7 = plt.subplot(gs[1, :2])
ax8 = plt.subplot(gs[1:, 2])
# -1表示倒数第一行
ax9 = plt.subplot(gs[-1, 0])
ax10 = plt.subplot(gs[-1, -2])

plt.show()

subplots()

借助subplots()方法,我们也可以分格显示图像

1
2
3
4
5
f, ((ax11, ax12), (ax13, ax14)) = plt.subplots(2, 2, sharex=True, sharey=True)

ax11.scatter([1, 2], [1, 2])
plt.tight_layout() # 紧凑显示图像
plt.show()

plot in plot 图中图

matplot支持我们在同一个figure里面,画多个图。也就是图中图。

先画一个大图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt

# 图中图
# 初始化figure
fig = plt.figure()

# 创建数据
x = [1, 2, 3, 4, 5, 6, 7]
y = [1, 3, 4, 2, 5, 8, 6]

# 画大图
# 确定大图左下角的位置以及宽高
left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
# 通过add_axes()方法,向figure里面添加第一个图
ax1 = fig.add_axes([left, bottom, width, height])
ax1.plot(x, y, 'r')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('title')

接着我们画左上角的小图

1
2
3
4
5
6
left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
ax2 = fig.add_axes([left, bottom, width, height])
ax2.plot(y, x, 'b')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('title inside 1')

然后是右下角的小图

1
2
3
4
5
6
7
plt.axes([0.6, 0.2, 0.25, 0.25])
plt.plot(y[::-1], x, 'g') # 注意对y进行了逆序处理
plt.xlabel('x')
plt.ylabel('y')
plt.title('title inside 2')
# 展示
plt.show()

Animation 动画

matplot支持我们展示动画,首先我们需要导入animation模块

1
2
3
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np

接下来我们定义一个0~2π内的正弦曲线

1
2
3
4
fig, ax = plt.subplots()
# 0~2π内的正弦曲线
x = np.arange(0, 2 * np.pi, 0.01)
line, = ax.plot(x, np.sin(x))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 定义动画
def animate(i):
line.set_ydata(np.sin(x + i / 10.0))
return line,


# 帧函数
def init():
line.set_ydata(np.sin(x))
return line,


ani = animation.FuncAnimation(fig=fig, # 进行动画绘制的figure
func=animate, # 自定义动画函数
frames=100, # 动画长度,一次循环包含的帧数
init_func=init, # 自定义开始帧
interval=20, # 更新频率,以ms计
blit=False # 选择更新所有点,还是仅更新产生变化的点。应选择True,但mac用户请选择False,否则无法显示动画
)

plt.show()

保存为视频

1
ani.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])

当然,如果报错的话,记得安装一下ffmpeg或者mencoder,例如mac下:

1
brew install ffmpeg

保存为gif图

1
ani.save('basic_animation.gif', writer='imagemagick', fps=60)