Matplotlib is hiring a Research Software Engineering Fellow! See discourse for details. Apply by January 3, 2020
如何创建轴的网格形状组合。
subplots()
- 可能是用来创建图形和轴的主要函数。它也类似于
matplotlib.pyplot.subplot()
,但同时创建和放置图形上的所有轴。也见matplotlib.Figure.subplots
.GridSpec
- 指定要放置子批次的网格的几何图形。需要设置网格的行数和列数。或者,可以调整子批次布局参数(例如,左、右等)。
SubplotSpec
- 指定子批次在给定子批次中的位置 GridSpec .
subplot2grid()
- 类似于
subplot()
,但使用基于0的索引并让子块占据多个单元格。本教程不介绍此功能。
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
前两个示例演示了如何使用这两种方法创建基本的2×2网格 subplots()
和 gridspec
.
使用 subplots()
很简单。它返回一个 Figure
实例和数组 Axes
物体。
fig1, f1_axes = plt.subplots(ncols=2, nrows=2, constrained_layout=True)
对于这样一个简单的用例, gridspec
可能过于冗长。你必须创造人物 GridSpec
分别执行实例,然后将gridspec实例的元素传递给 add_subplot()
方法创建轴对象。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])
gridspec的强大之处在于能够创建跨越行和列的子块。注意 Numpy slice 用于选择每个子块将占用的gridspec部分的语法。
请注意,我们还使用了便利方法 Figure.add_gridspec
而不是 gridspec.GridSpec
,可能会为用户保存导入,并保持命名空间的清洁。
fig3 = plt.figure(constrained_layout=True)
gs = fig3.add_gridspec(3, 3)
f3_ax1 = fig3.add_subplot(gs[0, :])
f3_ax1.set_title('gs[0, :]')
f3_ax2 = fig3.add_subplot(gs[1, :-1])
f3_ax2.set_title('gs[1, :-1]')
f3_ax3 = fig3.add_subplot(gs[1:, -1])
f3_ax3.set_title('gs[1:, -1]')
f3_ax4 = fig3.add_subplot(gs[-1, 0])
f3_ax4.set_title('gs[-1, 0]')
f3_ax5 = fig3.add_subplot(gs[-1, -2])
f3_ax5.set_title('gs[-1, -2]')
gridspec
对于通过两种方法创建不同宽度的子批次也是必不可少的。
这里显示的方法与上面的方法类似,初始化统一的网格规范,然后使用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)
另一种选择是使用 width_ratios
和 height_ratios
参数。这些关键字参数是数字列表。请注意,绝对值没有意义,只有它们的相对比率才重要。那意味着 width_ratios=[2, 4, 8]
等于 width_ratios=[1, 2, 4]
在同样宽的数字内。为了演示,我们将在 for
循环,因为我们以后不需要它们。
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')
学会使用 width_ratios
和 height_ratios
特别有用,因为顶级功能 subplots()
接受他们在 gridspec_kw
参数。就这一点而言,任何被 GridSpec
可以传递给 subplots()
通过 gridspec_kw
参数。此示例在不直接使用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')
这个 subplots
和 gridspec
方法可以组合,因为有时使用 subplots
然后取下一些并合并。这里我们创建一个布局,最后一列中底部的两个轴组合在一起。
fig7, f7_axs = plt.subplots(ncols=3, nrows=3)
gs = f7_axs[1, 2].get_gridspec()
# remove the underlying 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()
显式使用gridspec时,可以调整从gridspec创建的子批次的布局参数。注意:此选项与不兼容 constrained_layout
或 Figure.tight_layout
两者都可以调整子批次大小来填充数字。
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])
这和 subplots_adjust()
但它只影响从给定的gridspec创建的子批次。
例如,比较此图的左侧和右侧:
fig9 = plt.figure(constrained_layout=False)
gs1 = fig9.add_gridspec(nrows=3, ncols=3, left=0.05, right=0.48,
wspace=0.05)
f9_ax1 = fig9.add_subplot(gs1[:-1, :])
f9_ax2 = fig9.add_subplot(gs1[-1, :-1])
f9_ax3 = fig9.add_subplot(gs1[-1, -1])
gs2 = fig9.add_gridspec(nrows=3, ncols=3, left=0.55, right=0.98,
hspace=0.05)
f9_ax4 = fig9.add_subplot(gs2[:, :-1])
f9_ax5 = fig9.add_subplot(gs2[:-1, -1])
f9_ax6 = fig9.add_subplot(gs2[-1, -1])
您可以从 SubplotSpec
,在这种情况下,其布局参数设置为给定子批次规范的位置。
注意这也可以从更详细的 gridspec.GridSpecFromSubplotSpec
.
fig10 = plt.figure(constrained_layout=True)
gs0 = fig10.add_gridspec(1, 2)
gs00 = gs0[0].subgridspec(2, 3)
gs01 = gs0[1].subgridspec(3, 2)
for a in range(2):
for b in range(3):
fig10.add_subplot(gs00[a, b])
fig10.add_subplot(gs01[b, a])
下面是一个更复杂的嵌套gridspec示例,我们在外部4x4网格的每个单元格周围放置一个框,通过在内部3x3网格中隐藏适当的尖刺。
import numpy as np
from itertools import product
def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
return np.sin(i*a)*np.cos(i*b), np.sin(i*c)*np.cos(i*d)
fig11 = plt.figure(figsize=(8, 8), constrained_layout=False)
# gridspec inside gridspec
outer_grid = fig11.add_gridspec(4, 4, wspace=0.0, hspace=0.0)
for i in range(16):
inner_grid = outer_grid[i].subgridspec(3, 3, wspace=0.0, hspace=0.0)
a, b = int(i/4)+1, i % 4+1
for j, (c, d) in enumerate(product(range(1, 4), repeat=2)):
ax = plt.Subplot(fig11, inner_grid[j])
ax.plot(*squiggle_xy(a, b, c, d))
ax.set_xticks([])
ax.set_yticks([])
fig11.add_subplot(ax)
all_axes = fig11.get_axes()
# show only the outside spines
for ax in all_axes:
for sp in ax.spines.values():
sp.set_visible(False)
if ax.is_first_row():
ax.spines['top'].set_visible(True)
if ax.is_last_row():
ax.spines['bottom'].set_visible(True)
if ax.is_first_col():
ax.spines['left'].set_visible(True)
if ax.is_last_col():
ax.spines['right'].set_visible(True)
plt.show()