Matplotlib绘制子图

518 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

多个子图的合成

有时,我们希望检查数据的多个方面。例如,查看一个地区的天气状况,我们不仅希望得到时间与温度的关系,同时我们也需要关注时间与风力、PM2.5等方面之间的关系,此时我们希望同时展现时间-温度、时间-风力、时间-PM2.5三个不同的图形,Matplotlib提供了将多个图形组合在一起的方法。

import numpy as np
from matplotlib import pyplot as plt
t = np.linspace(-np.pi, np.pi, 1024)
grid_size = (4, 2)
plt.subplot2grid(grid_size, (0, 0), rowspan = 3, colspan = 1)
plt.plot(np.sin(2 * t), np.cos(0.5 * t), c = 'm')
plt.subplot2grid(grid_size, (0, 1), rowspan = 3, colspan = 1)
plt.plot(np.cos(3 * t), np.sin(t), c = 'c')
plt.subplot2grid(grid_size, (3, 0), rowspan=1, colspan=3)
plt.plot(np.cos(5 * t), np.sin(7 * t), c= 'y')
plt.tight_layout()
plt.show()

多个子图的合成

Tips:使用plt.subplot2grid()可以定义一个R行、C列的网格。然后,我们可以将一个图形渲染到所定义的网格中。 plt.subplot2grid()函数有四个常用参数:

  1. 第一个参数是网格的行数和列数,作为元组传递,例如我们想要一个R行、C列的网格,则需要传递(R,C)。
  2. 第二个参数用于确定图形在网格中的坐标,也作为元组传递。
  3. 可选参数rowspan定义图形将占据多少行。
  4. 可选参数colspan定义图形将占据多少列。

调用plt.subplot2grid()后,对plt绘图的下一次调用将在指定的矩形区域内绘制图形,同理,要在网格的另一个区域中绘制下一个图形,需要再次调用plt.subplot2grid()。 在示例中,定义了一个2x4的网格。前两个图形占据了1列、3行,第三个图形占据了两列、一行。一旦绘制了所有的图形,就需要调用pyplot.tight_layout()按照定义自动排列所有图形,确保它们彼此不重叠。

为每个子图添加标题

我们已经可以将多个子图合成在一个图形中,但是每个子图可能还需要有自己的标题,可以使用plt.title()为每个子图添加标题:

import numpy as np
from matplotlib import pyplot as plt
def get_radius(t, params):
    m, n_1, n_2, n_3 = params
    u = (m * t) / 4
    return (np.fabs(np.cos(u)) ** n_2 + np.fabs(np.sin(u)) ** n_3) ** (-1. / n_1)
grid_size = (3, 4)
t = np.linspace(0, 2 * np.pi, 1024)
for i in range(grid_size[0]):
    for j in range(grid_size[1]):
        params = np.random.randint(1, 20+1, size = 4)
        r = get_radius(t, params)
        plt.subplot2grid(grid_size, (i, j), rowspan=1, colspan=1)
        plt.plot(r * np.cos(t), r * np.sin(t), c = 'c')
        plt.title('%d, %d, %d, %d' % tuple(params), fontsize = 'small')
plt.suptitle("Example of plt.suptitle")
plt.tight_layout()
plt.show()

为每个子图添加标题

Tips:plt.title()函数可以为每一个图形提供一个标题,但此时,如果我们需要为整个图形提供一个标题,则应该使用plt.suptitle()函数。

子图合成的另一种方法

上述的子图合成方法具有通用性,可以使用它创建复杂的布局,但如果我们只需要在同一行或同一列中绘制多个子图,则可以使用更简洁的代码:

import numpy as np
from matplotlib import pyplot as plt
t = np.linspace(-np.pi, np.pi, 1024)
fig, (ax0, ax1, ax2) = plt.subplots(ncols =3)
ax0.plot(np.sin(2 * t), np.cos(0.5 * t), c = 'c')
ax1.plot(np.cos(3 * t), np.sin(t), c = 'c')
ax2.plot(np.cos(3 * t), np.sin(2 * t), c = 'c')
plt.tight_layout()
plt.show()

子图合成的另一种方法

Tips:plt.subplots()函数接受两个可选参数ncols和nrows,并返回一个带有ncols*nrows轴实例的Figure对象。轴实例按nrows行、ncols列排列在网格中。

更简洁的方法

虽然上述两种方法都可以实现合成子图的应用需求,但是我们需要的远不止此,我们可能想要更简洁的方法,而plt.subplot()函数就是我们所需要的。

import numpy as np
from matplotlib import pyplot as plt
def get_radius(t, params):
    m, n_1, n_2, n_3 = params
    u = (m * t) / 4
    return (np.fabs(np.cos(u)) ** n_2 + np.fabs(np.sin(u)) ** n_3) ** (-1. / n_1)
grid_size = (3, 4)
t = np.linspace(0, 2 * np.pi, 1024)
for i in range(grid_size[0] * grid_size[1]):
    params = np.random.random_integers(1, 20, size = 4)
    r = get_radius(t, params)
    plt.subplot(grid_size[0], grid_size[1], i+1)
    plt.plot(r * np.cos(t), r * np.sin(t), c = 'c')
    plt.title('%d, %d, %d, %d' % tuple(params), fontsize = 'small')
plt.suptitle("Example of plt.suptitle")
plt.tight_layout()
plt.show()

更简洁的方法

Tips:plt.subplot()函数接收三个参数,分别为行数,列数,以及子图的位序,直接指定划分网格的方式和需要绘图的位置索引。

系列链接

Matplotlib常见统计图的绘制

Matplotlib使用自定义颜色绘制统计图

Matplotlib控制线条样式和线宽

Matplotlib自定义样式绘制精美统计图

Matplotlib在图形中添加文本说明

Matplotlib在图形中添加注释

Matplotlib在图形中添加辅助网格和辅助线

Matplotlib添加自定义形状

Matplotlib控制坐标轴刻度间距和标签

Matplotlib使用对数刻度和极坐标