前言
这篇文章主要学习如何根据GridSpec和一些其他的函数实现自定义图形布局
使用GridSpec和其他函数自定义图形布局
以下函数或方法实现创建axes上的网格的组合
或许是创建figures和axes最主要的方式,与 matplotlib.pyplot.subplot()
类似,
但是同时创建并放置图形上的所有轴。更多详情请看matplotlib.figure.Figure.subplots
.
指定将放置子图的网格的几何形状。
需要设置网格的行数和列数。以及子图的布局参数可以调整
在给定的GridSpec上指定子图的位置
一个类似于subplot()
的辅助函数,但是使用基于0的索引并让subplot占用多个单元格。本文章没有介绍该函数。
导入
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
快速入门指南
使用
subplots()
非常简单。它返回一个Figure
实例和一个Axes
对象数组 。
fig1,f1_axes = plt.subplots(ncols=2,nrows=2,constrained_layout=True)
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/25/a84efe42f06c675b465982ed43f3c331.png)
对于像上面这样的简单用例,
gridspec
可能过于冗长。你必须分别创建图形和
GridSpec
实例,然后将gridspec实例的元素传递给add_subplot()
函数来创建axes对象。gridspec元素的访问方式通常与numpy数组相同。
fig2 = plt.figure(constrained_layout=True)
spec2 = gridspec.GridSpec(ncols=2,nrows=2,figure=fig2)
f2_ax1 = fig2.add_subplot(spec2[0,0])
f2_ax2 = fig2.add_subplot(spec2[0,1])
f2_ax3 = fig2.add_subplot(spec2[1,0])
f2_ax4 = fig2.add_subplot(spec2[1,1])
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/25/c8cfe4f0d45137f5ed014a638a7a928f.png)
可以看出和subplots()方式结果相同
gridspec的强大之处在于能够创建跨越行和列的子图。注意,NumPy slice Syntax 用于选择每个子图将占据的gridspec部分。
请注意,我们还使用了便捷方法Figure.add_gridspec
代替gridspec.GridSpec
,有可能为用户节省了导入时间,并使名称空间更整洁。
fig3 = plt.figure(constrained_layout=True)
gs = fig3.add_gridspec(3,3)
#关于切片可参考另一篇文章Numpy学习中的切片学习
f3_ax1 = fig3.add_subplot(gs[0,:])
f3_ax1.set_title('gs[0,:]')
f3_ax1 = fig3.add_subplot(gs[1,:-1])
f3_ax1.set_title('gs[1,:-1]')
f3_ax1 = fig3.add_subplot(gs[1:,-1])
f3_ax1.set_title('gs[1:,-1]')
f3_ax1 = fig3.add_subplot(gs[-1,0])
f3_ax1.set_title('gs[-1,0]')
f3_ax1 = fig3.add_subplot(gs[-1,-2])
f3_ax1.set_title('gs[-1,-2]')
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/25/1771e7f2c924222450b23f0d99d3d6de.png)
接下来展示的方法与上面的方法类似,
初始化统一的网格规范,然后使用numpy索引和切片为给定的子图分配多个“单元格”。
fig4 = plt.figure(constrained_layout=True)
spec4 = fig4.add_gridspec(ncols=2,nrows=2)
anno_opts = dict(xy=(0.5,0.5),xycoords='axes fraction',va='center',ha='center')
f4_ax1 = fig4.add_subplot(spec4[0,0])
f4_ax1.annotate('GridSpec[0,0]',**anno_opts)
fig4.add_subplot(spec4[0, 1]).annotate('GridSpec[0, 1:]', **anno_opts)
fig4.add_subplot(spec4[1, 0]).annotate('GridSpec[1:, 0]', **anno_opts)
fig4.add_subplot(spec4[1, 1]).annotate('GridSpec[1:, 1:]', **anno_opts)
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/25/03e448d6ea58673cb436c7f295203f59.png)
另一个方式是使用width_ratios和height_ratios参数。这些关键字参数是数字列表。
请注意,绝对值是没有意义的,只有它们的相对比率重要。这意味着width_ratio =[2, 4, 8]与width_ratio =[1, 2, 4]在同样宽的数字内相等。
fig5 = plt.figure(constrained_layout=True)
widths = [2,3,1.5]
heights = [1,3,2]
spec5 = fig5.add_gridspec(ncols=3,nrows=3,width_ratios=widths,height_ratios=heights)
for row in range(3):
for col in range(3):
ax = fig5.add_subplot(spec5[row,col])
label = 'Width: {}\nHeight: {}'.format(widths[col],heights[row])
ax.annotate(label,(0.1,0.5),xycoords='axes fraction',va='center')
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/25/41445b35cc1d0c8b71c98c482ba277cb.png)
学习使用width_ratio和height_ratio特别有用,因为函数
subplots()
在gridspec_kw参数中接受它们。为此,
GridSpec
接受的任何参数都可以通过gridspec_kw参数传递给subplots()
。此示例在不直接使用gridspec实例的情况下重新创建前面的图。
gs_kw = dict(width_ratios=widths,height_ratios=heights)
fig6,f6_axes = plt.subplots(ncols=3,nrows=3,constrained_layout=True,gridspec_kw=gs_kw)
for r,row in enumerate(f6_axes):
for c,ax in enumerate(row):
label = 'Width:{}\nHeight:{}'.format(widths[c],heights[r])
ax.annotate(label,(0.1,0.5),xycoords='axes fraction',va='center')
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/25/b918ee705c15a77a63e27fdc6b63fc80.png)
subplots和get_gridspec方法可以组合使用,因为有时使用subplots创建大多数子图,然后删除其中一些并组合它们更方便。
在这里,我们将最后一列中底部的两个轴组合起来创建一个布局。
fig7,f7_axs = plt.subplots(ncols=3,nrows=3)
gs = f7_axs[1,2].get_gridspec()
#删除[1,-1],[2,-1]的axes
for ax in f7_axs[1:,-1]:
ax.remove()
axbig = fig7.add_subplot(gs[1:,-1])
axbig.annotate('Big Axes \nGridSpec[1:, -1]', (0.1, 0.5),
xycoords='axes fraction', va='center')
#调整子图之间及其周围的填充。
fig7.tight_layout()
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/25/fd722ff151b1ec23501358966706ccfa.png)
精细调整Gridspec布局
当显示地使用GridSpec时,可以通过改变gridspec的参数来调整子图的布局
请注意,此选项与constrained_layout
或者 Figure.tight_layout
都不兼容,两者都通过调整子图大小以填充figure。
参数请看:matplotlib.gridspec.GridSpec
fig8 = plt.figure(constrained_layout=False)
gs1 = fig8.add_gridspec(nrows=3,ncols=3,left=0.05,right=0.48,wspace=0.05)
f8_ax1 = fig8.add_subplot(gs1[:-1,:])
f8_ax2 = fig8.add_subplot(gs1[-1,:-1])
f8_ax3 = fig8.add_subplot(gs1[-1,-1])
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/26/9af56c0dbbb846fa118121498dc6b478.png)
GridSpec之SubplotSpec
你可以通过SubplotSpec
创建GridSpec,在这种情况下,它的布局参数被设置为给定SubplotSpec的位置。
fig10 = plt.figure(constrained_layout=False)
gs0 = fig10.add_gridspec(1,2)
gs00 = gs0[0].subgridspec(2,3)
gs01 = gs0[1].subgridspec(3,2)
for i in range(2):
for j in range(3):
fig10.add_subplot(gs00[i,j])
fig10.add_subplot(gs01[j,i])
![](https://cdn.jsdelivr.net/gh/zangwhe/Image@main/2020/11/26/d9c94e19a272e34c530f3ae846026b68.png)
如果你发现文章中出现的错误或者有任何疑问欢迎在下方评论区留言
点个赞和关注支持一下啦.