Matplotlib子图划分——均匀绘图(详细介绍)

959 阅读4分钟

一、导读

在论文或者PPT展示,我们经常会遇到这种图片:

4.png

可以看出,上面的图是由两个子图组合而成的,两个图尺寸一样大。也会遇到下面这类图片:

03.png

与第一张图相比,这个图也分为左右两部分,但是左右子图所占画布不均。

这两类图是PPT或论文中常见的图,笔者把它分为:均匀绘图、非均匀绘图。均匀绘图特点是:1)每个子图所占的尺寸一致;2)各个子图表达的内容大致相同。非均匀绘图的特点是:1)每个/部分子图尺寸不一致;2)子图中存在包含关系,小的子图是大的子图在不同尺度下的分解表现。

主要内容是:介绍Matplotlib的均匀绘图的几个函数:subplot、add_subplot、subplots、subplot_mosaic

均匀绘图的语法

1)subplot函数 (此函数也可以用于不规则绘图)

语法: plt.subplot(nrows, ncols, index, **kwargs)

nrows:绘图的行数
ncols:绘图的列数
index:绘图的索引,从上到下,从左至右,索引从1开始。

**kwargs:对绘图区有额外要求可以使用,例如要求背景色等等,具体参考:matplotlib.org/stable/api/…

例如:ax1 = plt.subplot(221),表示创建一个2行2列的画布,选择索引为1进行绘图。plt.subplot是一个axes对象,可以用axes的属性方法,文中已介绍了常用方法。

下面是一个示例:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

plt.figure() #创建画布

x = np.linspace(-5, 5, 100)
y = np.sin(x)
ax1 = plt.subplot(2, 2, 1) #将画布划分为2行2列,共4个子图,选择第1个子区绘图
ax1.plot(x, y, linewidth = 2, c = 'k', label = 'y = sin(x)')
ax1.legend() #显示图例

ax2 = plt.subplot(224) #将画布划分为2行2列,共4个子图,选择第4个子区绘图
y = np.random.randint(-5, 5, (100, 1))
ax2.scatter(x, y, s = 20, c = 'k') 
plt.show()

4.png

代码中创建了2*2的子图,第一幅图选择索引为1进行绘制(左上角)、第二幅图选择索引为2进行绘制(右下角)

2)add_subplot函数(此函数也可用于不规则绘图)

语法:fig.add_subplot(nrows, ncols, index, **kwargs)

参数解释与plt.subplot()很类似。 例如:ax1 = fig.add_subplot(2, 2, 1),表示创建一个2行2列的画布,选择索引为1进行绘图。fig,add_subplot()是一个axes对象。

fig = plt.figure() 
x = np.linspace(-5, 5, 100)
y = np.sin(x)
ax1 = fig.add_subplot(2, 2, 1) #将画布划分为2行2列,共4个子图,并选择第1个子区
ax1.plot(x, y, linewidth = 2, c = 'k', label = 'y = sin(x)')

ax2 = fig.add_subplot(2, 2, 4) #将画布划分为2行2列,共4个子图,并选择第4个子区
y = np.random.randint(-5, 5, (100, 1))
ax2.scatter(x, y, s = 20, c = 'k')
plt.show()

5.png

可以看出绘制的结果与上图效果一致。

3)subplots函数(此函数仅能进行规则绘图)

语法: fig, ax = plt.subplots(ncols = 列数, nrows = 行数, figsize = 图片大小)

绘图时是对ax进行操作,ax返回的是一个包含多个子图的axes对象列表,使用时按照列表索引进行读取即可(注意,每一行为一个列表)。

下面是一个示例:

import matplotlib.pyplot as plt
#画布划分为一个2行3列的子区
fig, ax = plt.subplots(2, 3, figsize = (8, 8)) 
print(ax)

返回结果为:

8.png

可以看出,利用subplots返回的ax是一个列表,创建了2行3列的绘图,返回的列表也是2行3列。如果我们想要在某个子区绘图,例如第2个,我们调用axes = ax[0][1],即可获取第一行和第二列的子区。

fig, ax = plt.subplots(2, 3, figsize = (8, 8)) 
axes = ax[0][1#选择第一行第二列的子区绘图
x = np.linspace(0, 10, 100)
y = np.sin(x)
axes.plot(x, y, linewidth = 2, c = 'k')
plt.show()

7.png

4)subplot_mosaic函数

语法:fig, axs = plt.subplot_mosaic(子图别称,layout, figsize) #笔者常用这两个参数 第一个参数表示的是画布的子图布局, [['a', 'b', 'c'], ['d', 'e', 'f']]含义就是将画布分为6个子区,每个子区别称为abcdef。

调用的时候利用ax[别称]即可对应相应的子图,为axes对象。例如ax['a']代表的是a子图。 示例如下:

import matplotlib.pyplot as plt
fig, ax = plt.subplot_mosaic([['a', 'b', 'c'], ['d', 'e', 'f']])
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax['a'].plot(x, y) #调用第一个子图

9.png

该代码创建了一个画布,第一行子图别称分别为a,b,c,第二行子图别称分别为d,e,f。ax['a']选择了a子图,绘制了折线图。

上述代码的等价语法为:

import matplotlib.pyplot as plt
fig, ax = plt.subplot_mosaic('''ABC                           
                                D.F''')
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax['A'].plot(x, y) 

10.png

上面代码给出了另外一种绘制方式,其中"."代表了是个空白子区。

总结

本文总结了Matplotlib的均匀绘图的几个方式,可以通过subplot、add_subplot、subplots、subplot_mosaic函数来绘制,在论文或PPT汇报这种表达方式较为常见,需要好好掌握其中一种表达方式。

由于篇幅限制,本篇到此结束,下一节将介绍Matplotlib的非均匀绘图问题。此内容将在"python数据分析实践"公众号同步更新。如果您有更好的想法或对文章有其他建议,可以关注或评论留言。如果有想要了解其它的内容,也可以联系或评论,感谢您的阅读!