受约束的布局参考线

如何使用受约束的布局使图形中的绘图清晰匹配。

constrained_layout 自动调整子批次和装饰,如图例和颜色栏,以便它们适合图形窗口,同时尽可能保留用户请求的逻辑布局。

constrained_layout 类似于 tight_layout ,但使用约束解算器来确定允许它们匹配的轴的大小。

constrained_layout 需要在将任何轴添加到图形之前激活。有两种方法可以做到这一点

以下各节将详细介绍这些内容。

警告

当前受约束的布局为 实验的 . 行为和API可能会发生变化,或者整个功能可能会在没有折旧期的情况下被删除。如果你 要求 您的绘图是绝对可复制的,在运行受约束的布局和使用后获取轴位置 ax.set_position() 在您的代码中 constrained_layout=False .

简单实例

在Matplotlib中,轴(包括子图)的位置以标准化图形坐标指定。轴标签或标题(有时甚至勾选标签)可能会超出图形区域,因此会被剪切。

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.gridspec as gridspec
import numpy as np


plt.rcParams['savefig.facecolor'] = "0.8"
plt.rcParams['figure.figsize'] = 4.5, 4.
plt.rcParams['figure.max_open_warning'] = 50


def example_plot(ax, fontsize=12, hide_labels=False):
    ax.plot([1, 2])

    ax.locator_params(nbins=3)
    if hide_labels:
        ax.set_xticklabels([])
        ax.set_yticklabels([])
    else:
        ax.set_xlabel('x-label', fontsize=fontsize)
        ax.set_ylabel('y-label', fontsize=fontsize)
        ax.set_title('Title', fontsize=fontsize)


fig, ax = plt.subplots(constrained_layout=False)
example_plot(ax, fontsize=24)
Title

为了防止这种情况发生,需要调整轴的位置。对于子批次,这可以通过调整子批次参数来完成。 (移动轴的边缘,为刻度标签留出空间 )但是,使用 constrained_layout=True Kwarg将自动进行调整。

fig, ax = plt.subplots(constrained_layout=True)
example_plot(ax, fontsize=24)
Title

当有多个子批次时,通常会看到不同轴的标签相互重叠。

fig, axs = plt.subplots(2, 2, constrained_layout=False)
for ax in axs.flat:
    example_plot(ax)
Title, Title, Title, Title

指定 constrained_layout=True 在召唤 plt.subplots 使布局受到适当的约束。

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flat:
    example_plot(ax)
Title, Title, Title, Title

彩条

如果用 Figure.colorbar ,你需要为它腾出空间。 constrained_layout 自动执行此操作。请注意,如果您指定 use_gridspec=True 它将被忽略,因为此选项用于通过 tight_layout .

注解

对于 pcolormesh 关键字参数 (pc_kwargs )我们用字典。下面我们将为多个轴指定一个颜色条,每个轴包含 ScalarMappable ;指定norm和colormap可确保颜色栏对于所有轴都是精确的。

arr = np.arange(100).reshape((10, 10))
norm = mcolors.Normalize(vmin=0., vmax=100.)
# see note above: this makes all pcolormesh calls consistent:
pc_kwargs = {'rasterized': True, 'cmap': 'viridis', 'norm': norm}
fig, ax = plt.subplots(figsize=(4, 4), constrained_layout=True)
im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=ax, shrink=0.6)
constrainedlayout guide

出:

<matplotlib.colorbar.Colorbar object at 0x7fa9c011d048>

如果将轴(或其他可ITerable容器)列表指定给 ax 的参数 colorbar ,受约束的布局将占用指定轴的空间。

fig, axs = plt.subplots(2, 2, figsize=(4, 4), constrained_layout=True)
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
constrainedlayout guide

出:

<matplotlib.colorbar.Colorbar object at 0x7fa9bcd96ac8>

如果从轴网格内指定轴列表,颜色栏将适当地窃取空间并留有间隙,但所有子图的大小仍然相同。

fig, axs = plt.subplots(3, 3, figsize=(4, 4), constrained_layout=True)
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs[1:, ][:, 1], shrink=0.8)
fig.colorbar(im, ax=axs[:, -1], shrink=0.6)
constrainedlayout guide

出:

<matplotlib.colorbar.Colorbar object at 0x7fa9bf7ec1d0>

请注意,将单个轴指定为父轴时有一点微妙。在下面的内容中,颜色条可能需要并期望对齐,但它们不是这样的,因为与底轴配对的颜色条与轴的子产品规格绑定,因此在添加网格规格级别的颜色条时会收缩。

fig, axs = plt.subplots(3, 1, figsize=(4, 4), constrained_layout=True)
for ax in axs[:2]:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs[:2], shrink=0.6)
im = axs[2].pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs[2], shrink=0.6)
constrainedlayout guide

出:

<matplotlib.colorbar.Colorbar object at 0x7fa9fc858d68>

使单个轴的行为类似于轴列表的API将其指定为列表(或其他可ITerable容器),如下所示:

fig, axs = plt.subplots(3, 1, figsize=(4, 4), constrained_layout=True)
for ax in axs[:2]:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs[:2], shrink=0.6)
im = axs[2].pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=[axs[2]], shrink=0.6)
constrainedlayout guide

出:

<matplotlib.colorbar.Colorbar object at 0x7fa9fca88e10>

副标题

constrained_layout 也可以为 suptitle .

fig, axs = plt.subplots(2, 2, figsize=(4, 4), constrained_layout=True)
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
fig.suptitle('Big Suptitle')
Big Suptitle

出:

Text(0.5, 0.9895825, 'Big Suptitle')

传说

图例可以放置在其父轴之外。受约束的布局设计用于处理 Axes.legend() . 但是,受约束的布局确实 not 处理通过创建的图例 Figure.legend() (然而)

fig, ax = plt.subplots(constrained_layout=True)
ax.plot(np.arange(10), label='This is a plot')
ax.legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
constrainedlayout guide

出:

<matplotlib.legend.Legend object at 0x7fa9bcf1c198>

但是,这将从子地块布局中窃取空间:

fig, axs = plt.subplots(1, 2, figsize=(4, 2), constrained_layout=True)
axs[0].plot(np.arange(10))
axs[1].plot(np.arange(10), label='This is a plot')
axs[1].legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
constrainedlayout guide

出:

<matplotlib.legend.Legend object at 0x7fa9bceb72e8>

为了让图例人物或其他艺术家 not 从子地块布局中窃取空间,我们可以 leg.set_in_layout(False) . 当然,这可能意味着这个传说最终会出现,但如果随后用 fig.savefig('outname.png', bbox_inches='tight') . 但是,请注意,传说 get_in_layout 必须再次切换状态才能使保存的文件正常工作,如果希望在打印前通过受约束的布局调整轴的大小,则必须手动触发绘图。

fig, axs = plt.subplots(1, 2, figsize=(4, 2), constrained_layout=True)

axs[0].plot(np.arange(10))
axs[1].plot(np.arange(10), label='This is a plot')
leg = axs[1].legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
leg.set_in_layout(False)
# trigger a draw so that constrained_layout is executed once
# before we turn it off when printing....
fig.canvas.draw()
# we want the legend included in the bbox_inches='tight' calcs.
leg.set_in_layout(True)
# we don't want the layout to change at this point.
fig.set_constrained_layout(False)
fig.savefig('../../doc/_static/constrained_layout_1b.png',
            bbox_inches='tight', dpi=100)
constrainedlayout guide

保存的文件如下:

../../_images/constrained_layout_1b.png

解决这种尴尬的更好方法是简单地使用 Figure.legend

fig, axs = plt.subplots(1, 2, figsize=(4, 2), constrained_layout=True)
axs[0].plot(np.arange(10))
lines = axs[1].plot(np.arange(10), label='This is a plot')
labels = [l.get_label() for l in lines]
leg = fig.legend(lines, labels, loc='center left',
                 bbox_to_anchor=(0.8, 0.5), bbox_transform=axs[1].transAxes)
fig.savefig('../../doc/_static/constrained_layout_2b.png',
            bbox_inches='tight', dpi=100)
constrainedlayout guide

保存的文件如下:

../../_images/constrained_layout_2b.png

填充和间距

对于受约束的布局,我们在每个轴的边缘实现了填充。此填充设置距绘图边缘的距离,以及相邻绘图之间的最小距离。它由关键字参数以英寸为单位指定 w_padh_pad 对函数 set_constrained_layout_pads

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flat:
    example_plot(ax, hide_labels=True)
fig.set_constrained_layout_pads(w_pad=4/72, h_pad=4/72, hspace=0, wspace=0)

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flat:
    example_plot(ax, hide_labels=True)
fig.set_constrained_layout_pads(w_pad=2/72, h_pad=2/72, hspace=0, wspace=0)
  • constrainedlayout guide
  • constrainedlayout guide

子批次之间的间距由 wspacehspace . 作为一个整体,有指定为子批次组大小的一部分。如果图形的大小改变了,那么这些空间就会按比例变化。请注意,在下面,边上的空间与上面的不一样,但是子图之间的空间是变化的。

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flat:
    example_plot(ax, hide_labels=True)
fig.set_constrained_layout_pads(w_pad=2/72, h_pad=2/72, hspace=0.2, wspace=0.2)
constrainedlayout guide

带颜色条的间距

将放置色带 wspacehsapce 除了其他子批次。颜色条和它所连接的轴之间的填充永远不会小于 w_pad (对于垂直颜色条)或 h_pad (对于水平颜色条)。注意使用 pad 克瓦格在这里 colorbar 打电话。它默认为它所连接的轴的大小的0.02。

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flat:
    pc = ax.pcolormesh(arr, **pc_kwargs)
    fig.colorbar(pc, ax=ax, shrink=0.6, pad=0)
    ax.set_xticklabels('')
    ax.set_yticklabels('')
fig.set_constrained_layout_pads(w_pad=2/72, h_pad=2/72, hspace=0.2, wspace=0.2)
constrainedlayout guide

在上面的示例中,颜色条与绘图之间的距离永远不会超过2个点,但是如果我们希望它离得远一点,我们可以指定它的值 pad 非零。

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flat:
    pc = ax.pcolormesh(arr, **pc_kwargs)
    fig.colorbar(im, ax=ax, shrink=0.6, pad=0.05)
    ax.set_xticklabels('')
    ax.set_yticklabels('')
fig.set_constrained_layout_pads(w_pad=2/72, h_pad=2/72, hspace=0.2, wspace=0.2)
constrainedlayout guide

RCPARAMS

有五个 rcParams 可以在脚本或 matplotlibrc 文件。它们都有前缀 figure.constrained_layout

  • use :是否使用受约束的布局。默认值为假
  • w_padh_pad :在轴对象周围填充。
    表示英寸的浮动。默认值为3/72。英寸(3分)
  • wspacehspace :子批次组之间的空间。
    表示被分隔的子块宽度的一部分的浮点。默认值为0.02。
plt.rcParams['figure.constrained_layout.use'] = True
fig, axs = plt.subplots(2, 2, figsize=(3, 3))
for ax in axs.flat:
    example_plot(ax)
Title, Title, Title, Title

与网格规范一起使用

约束布局用于 subplots()GridSpec()add_subplot() .

注意以下内容 constrained_layout=True

fig = plt.figure()

gs1 = gridspec.GridSpec(2, 1, figure=fig)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])

example_plot(ax1)
example_plot(ax2)
Title, Title

更复杂的gridspec布局是可能的。注意这里我们使用方便函数 add_gridspecsubgridspec .

fig = plt.figure()

gs0 = fig.add_gridspec(1, 2)

gs1 = gs0[0].subgridspec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])

example_plot(ax1)
example_plot(ax2)

gs2 = gs0[1].subgridspec(3, 1)

for ss in gs2:
    ax = fig.add_subplot(ss)
    example_plot(ax)
    ax.set_title("")
    ax.set_xlabel("")

ax.set_xlabel("x-label", fontsize=12)
Title, Title

出:

Text(0.5, 22.166999999999994, 'x-label')

请注意,在上面的左侧和列没有相同的垂直范围。如果我们希望两个网格的顶部和底部对齐,则它们需要位于同一网格规格中:

fig = plt.figure()

gs0 = fig.add_gridspec(6, 2)

ax1 = fig.add_subplot(gs0[:3, 0])
ax2 = fig.add_subplot(gs0[3:, 0])

example_plot(ax1)
example_plot(ax2)

ax = fig.add_subplot(gs0[0:2, 1])
example_plot(ax)
ax = fig.add_subplot(gs0[2:4, 1])
example_plot(ax)
ax = fig.add_subplot(gs0[4:, 1])
example_plot(ax)
Title, Title, Title, Title, Title

此示例使用两个gridspec使颜色栏仅与一组pcolor相关。请注意,由于这个原因,左边的列比右边的两列宽。当然,如果您希望子块的大小相同,您只需要一个gridspec。

def docomplicated(suptitle=None):
    fig = plt.figure()
    gs0 = fig.add_gridspec(1, 2, figure=fig, width_ratios=[1., 2.])
    gsl = gs0[0].subgridspec(2, 1)
    gsr = gs0[1].subgridspec(2, 2)

    for gs in gsl:
        ax = fig.add_subplot(gs)
        example_plot(ax)
    axs = []
    for gs in gsr:
        ax = fig.add_subplot(gs)
        pcm = ax.pcolormesh(arr, **pc_kwargs)
        ax.set_xlabel('x-label')
        ax.set_ylabel('y-label')
        ax.set_title('title')

        axs += [ax]
    fig.colorbar(pcm, ax=axs)
    if suptitle is not None:
        fig.suptitle(suptitle)

docomplicated()
Title, Title, title, title, title, title

手动设置轴位置

可以有很好的理由手动设置轴位置。手动呼叫 set_position 将设置轴,使受约束的布局不再对其产生影响。(请注意,受约束的布局仍为移动的轴保留空间)。

fig, axs = plt.subplots(1, 2)
example_plot(axs[0], fontsize=12)
axs[1].set_position([0.2, 0.2, 0.4, 0.4])
Title

如果要在数据空间中插入轴,则需要使用 fig.execute_constrained_layout() 打电话。然后将正确定位插入的图形。但是,如果图形的大小随后发生变化,则无法正确定位。同样,如果将图形打印到另一个后端,则由于后端渲染字体的方式存在细微差异,因此位置可能会略有变化。

from matplotlib.transforms import Bbox

fig, axs = plt.subplots(1, 2)
example_plot(axs[0], fontsize=12)
fig.execute_constrained_layout()
# put into data-space:
bb_data_ax2 = Bbox.from_bounds(0.5, 1., 0.2, 0.4)
disp_coords = axs[0].transData.transform(bb_data_ax2)
fig_coords_ax2 = fig.transFigure.inverted().transform(disp_coords)
bb_ax2 = Bbox(fig_coords_ax2)
ax2 = fig.add_axes(bb_ax2)
Title

手动关闭 constrained_layout

constrained_layout 通常调整图形每次绘制时的轴位置。如果您想获得 constrained_layout 但不更新,然后进行初始绘制,然后调用 fig.set_constrained_layout(False) . 这对于勾号标签可能更改长度的动画可能很有用。

注意 constrained_layout 为关闭 ZOOMPAN 使用工具栏的后端的GUI事件。这可以防止轴在缩放和平移期间更改位置。

局限性

不兼容的函数

constrained_layout 无法处理通过创建的子地块 pyplot.subplot . 原因是 pyplot.subplot 创建单独的 GridSpec 实例和 constrained_layout 使用(嵌套)网格规格来执行布局。因此,以下内容无法产生一个良好的布局:

fig = plt.figure()

ax1 = plt.subplot(221)
ax2 = plt.subplot(223)
ax3 = plt.subplot(122)

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
Title, Title, Title

当然,可以使用网格规范进行布局:

fig = plt.figure()
gs = fig.add_gridspec(2, 2)

ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[1, 0])
ax3 = fig.add_subplot(gs[:, 1])

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
Title, Title, Title

同样地, subplot2grid() 不起作用的原因相同:每次调用都会创建一个不同的父gridspec。

fig = plt.figure()

ax1 = plt.subplot2grid((3, 3), (0, 0))
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
Title, Title, Title, Title

使此绘图与 constrained_layout 再次使用 gridspec 直接地

fig = plt.figure()
gs = fig.add_gridspec(3, 3)

ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1:])
ax3 = fig.add_subplot(gs[1:, 0:2])
ax4 = fig.add_subplot(gs[1:, -1])

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
Title, Title, Title, Title

其他注意事项

  • constrained_layout 只考虑滴答标签、轴标签、标题和图例。因此,其他艺术家可能被剪短,也可能重叠。
  • 它假定滴答标签、轴标签和标题所需的额外空间独立于轴的原始位置。这通常是正确的,但很少有不正确的情况。
  • 后端处理渲染字体的方式存在细微差异,因此结果将不完全相同。
  • 艺术家使用轴坐标超出轴边界将导致不寻常的布局时,添加到轴。通过将艺术家直接添加到 Figure 使用 add_artist() . 见 ConnectionPatch 举个例子。

调试

受约束的布局可能会以某种意外的方式失败。因为它使用一个约束解算器,解算器可以找到数学上正确的解,但这根本不是用户想要的。通常的故障模式是所有尺寸折叠到其最小允许值。如果发生这种情况,有两个原因:

  1. 您请求绘制的元素空间不足。
  2. 有一个bug-在这种情况下,请在https://github.com/matplotlib/matplotlib/issues上打开一个问题。

如果存在错误,请使用不需要外部数据或依赖项(numpy除外)的自包含示例进行报告。

算法注意事项

约束的算法相对简单,但由于我们布局图形的方法复杂,因此具有一定的复杂性。

图形布局

图按层次排列:

  1. 图: fig = plt.figure()
  1. GRIDSPEC gs0 = gridspec.GridSpec(1, 2, figure=fig)

    1. Subplotspec: ss = gs[0, 0]
      1. 轴: ax0 = fig.add_subplot(ss)
    2. Subplotspec: ss = gs[0, 1]
    1. Gridspec: gsR = gridspec.GridSpecFromSubplotSpec(2, 1, ss)

      • Subplotspec: ss = gsR[0, 0]

        • 轴: axR0 = fig.add_subplot(ss)
      • Subplotspec: ss = gsR[1, 0]

        • 轴: axR1 = fig.add_subplot(ss)

每个项目都有一个与之关联的layoutbox。使用创建的网格规格的嵌套 GridSpecFromSubplotSpec 可以任意深。

Axestwo LayOutbox。第一个, ax._layoutbox 表示轴的外部及其所有装饰(即记号标签、轴标签等)。第二个布局框对应于轴 ax.position 设置脊椎在图中的位置。

为什么有这么多集装箱?理想情况下,只需要轴布局框。对于gridspec,如果gridspec是通过 GridSpecFromSubplotSpec . 在顶层,对称是可取的,但也为 suptitle .

对于子图规格/轴的情况,轴通常有颜色条或其他需要打包在子图规格内的注释,因此需要外部层。

简单情况:一个轴

对于单个轴,布局是直接向前的。图形和外部网格规格的布局框一致。子批次规格和轴框也一致,因为轴没有颜色条。注意红色的区别 pos 盒子和绿色 ax 框由轴周围装饰的大小设置。

在代码中,这是通过 do_constrained_layout() 喜欢:

ax._poslayoutbox.edit_left_margin_min(-bbox.x0 + pos.x0 + w_padt)
from matplotlib._layoutbox import plot_children

fig, ax = plt.subplots(constrained_layout=True)
example_plot(ax, fontsize=24)
plot_children(fig, fig._layoutbox, printit=False)
Title

简单情况:两个轴

在这种情况下,轴布局框和子批次规格框仍然是共同的。然而,由于右地块中的装饰比左地块小得多,所以右中铺箱较小。

子批次规范框在子例程的代码中列出。 arange_subplotspecs() 它只检查代码中的子块规格,并对它们进行适当的堆叠。

两个 pos 轴排成一列。因为它们有相同的最小行,所以它们排在最上面。因为它们的最大行数相同,所以它们在底部排成一行。在代码中,这是通过调用 layoutbox.align . 如果有多行,则行之间将发生相同的水平对齐。

两个 pos 轴的宽度相同,因为子块规格占用相同的列数。这是在代码中完成的,其中 dcols0 被比作 dcolsC . 如果它们相等,那么它们的宽度就被限制为相等。

虽然在这种情况下有点微妙,但请注意,子图规范之间的划分是 not 居中,但已向右移动,以便为左侧绘图上较大的标签留出空间。

fig, ax = plt.subplots(1, 2, constrained_layout=True)
example_plot(ax[0], fontsize=32)
example_plot(ax[1], fontsize=8)
plot_children(fig, fig._layoutbox, printit=False)
Title, Title

两个轴和颜色条

添加颜色栏可以清楚地说明为什么子批次规格的layoutboxes必须不同于轴layoutboxes。在这里,我们看到左边的子产品规格有更多的空间来容纳 colorbar 有两个绿色的 ax 盒子里面的 ss 盒子。

请注意 pos 由于对宽度的限制,框仍然相同,因为它们的子块规格占用相同数量的列(本例中的一列)。

颜色栏布局逻辑包含在 make_axes which calls _ 约束的“layout.layoutColorBarSingle()``用于附加到单个轴的CBAR,以及 ``_constrained_layout.layoutcolorbargridspec() 如果颜色栏与网格规格相关联。

fig, ax = plt.subplots(1, 2, constrained_layout=True)
im = ax[0].pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=ax[0], shrink=0.6)
im = ax[1].pcolormesh(arr, **pc_kwargs)
plot_children(fig, fig._layoutbox, printit=False)
constrainedlayout guide

与网格规格关联的颜色条

此示例显示了由颜色栏layoutbox缩小的子批次规格layoutbox。颜色栏LayoutBox的大小设置为 shrink 小于 pos 网格规格中的布局框,并使其位于这两个点之间的中心。

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
plot_children(fig, fig._layoutbox, printit=False)
constrainedlayout guide

轴大小不均匀

在网格规格布局中,有两种方法可以使轴的大小不均匀,一种是将轴指定为跨网格规格行或列,另一种是指定宽度和高度比率。

这里使用第一种方法。使高度正确的约束在代码中, drowsC < drows0 在这种情况下,1小于2。因此,我们将1行轴的高度限制为小于2行轴高度的一半。

注解

如果附加在较小轴上的装饰非常大,则此算法可能是错误的,因此存在未计算的边缘情况。

fig = plt.figure(constrained_layout=True)
gs = gridspec.GridSpec(2, 2, figure=fig)
ax = fig.add_subplot(gs[:, 0])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[0, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[1, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
plot_children(fig, fig._layoutbox, printit=False)
constrainedlayout guide

高度和宽度比率与代码的相同部分相适应,较小的轴总是被限制为小于较大的轴。

fig = plt.figure(constrained_layout=True)
gs = gridspec.GridSpec(3, 2, figure=fig,
                       height_ratios=[1., 0.5, 1.5], width_ratios=[1.2, 0.8])
ax = fig.add_subplot(gs[:2, 0])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[2, 0])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[0, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[1:, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
plot_children(fig, fig._layoutbox, printit=False)
constrainedlayout guide

空的gridspec插槽

尚未解释的最后一段代码是,如果打开了一个空的gridspec,将会发生什么。在这种情况下,会添加一个假的不可见轴,我们会像以前一样继续。空网格规格没有装饰,但轴位置与占用的轴位置的大小相同。

这是在 _constrained_layout.do_constrained_layout() (hassubplotspec

fig = plt.figure(constrained_layout=True)
gs = gridspec.GridSpec(1, 3, figure=fig)
ax = fig.add_subplot(gs[0])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[-1])
im = ax.pcolormesh(arr, **pc_kwargs)
plot_children(fig, fig._layoutbox, printit=False)
plt.show()
constrainedlayout guide

其他音符

布局只调用一次。如果原始布局非常接近(在大多数情况下应该是这样的),这是可以的。但是,如果布局与默认布局相比有很大的变化,那么装饰师可以更改大小。尤其是x和ytick标签可以更改。如果发生这种情况,那么我们可能应该调用整个例程两次。

脚本的总运行时间: (0分18.407秒)

关键词:matplotlib代码示例,codex,python plot,pyplot Gallery generated by Sphinx-Gallery