Matplotlib is hiring a Research Software Engineering Fellow! See discourse for details. Apply by January 3, 2020

Version 3.1.1
matplotlib
Fork me on GitHub

目录

Related Topics

受约束的布局参考线

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

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

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

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

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

警告

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

简单实例

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

# sphinx_gallery_thumbnail_number = 18

#import matplotlib
#matplotlib.use('Qt5Agg')

import warnings

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

import matplotlib._layoutbox as layoutbox

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


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

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


fig, ax = plt.subplots(constrained_layout=False)
example_plot(ax, fontsize=24)
受约束的布局参考线

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

fig, ax = plt.subplots(constrained_layout=True)
example_plot(ax, fontsize=24)
受约束的布局参考线

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

fig, axs = plt.subplots(2, 2, constrained_layout=False)
for ax in axs.flatten():
    example_plot(ax)
受约束的布局参考线

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

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flatten():
    example_plot(ax)
受约束的布局参考线

彩条

如果用 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)
受约束的布局参考线

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

fig, axs = plt.subplots(2, 2, figsize=(4, 4), constrained_layout=True)
for ax in axs.flatten():
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
受约束的布局参考线

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

fig, axs = plt.subplots(3, 3, figsize=(4, 4), constrained_layout=True)
for ax in axs.flatten():
    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)
受约束的布局参考线

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

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)
受约束的布局参考线

使单个轴的行为类似于轴列表的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)
受约束的布局参考线

副标题

constrained_layout 也可以为 suptitle .

fig, axs = plt.subplots(2, 2, figsize=(4, 4), constrained_layout=True)
for ax in axs.flatten():
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
fig.suptitle('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))
受约束的布局参考线

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

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))
受约束的布局参考线

为了让传奇人物或其他艺术家 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('CL01.png', bbox_inches='tight', dpi=100)
受约束的布局参考线

保存的文件如下:

受约束的布局参考线

解决这种尴尬的更好方法是简单地使用 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('CL02.png', bbox_inches='tight', dpi=100)
受约束的布局参考线

保存的文件如下:

受约束的布局参考线

填充和间距

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

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flatten():
    example_plot(ax, nodec=True)
    ax.set_xticklabels('')
    ax.set_yticklabels('')
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.flatten():
    example_plot(ax, nodec=True)
    ax.set_xticklabels('')
    ax.set_yticklabels('')
fig.set_constrained_layout_pads(w_pad=2./72., h_pad=2./72.,
        hspace=0., wspace=0.)
  • 受约束的布局参考线
  • 受约束的布局参考线

子批次之间的间距由 wspacehspace . 指定为整个子批次组大小的一部分。如果图形的大小发生了变化,则这些空间将按比例变化。请注意,在吹制过程中,边缘的空间与上面的空间没有变化,但是子批次之间的空间会变化。

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flatten():
    example_plot(ax, nodec=True)
    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)
受约束的布局参考线

带颜色条的间距

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

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flatten():
    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)
受约束的布局参考线

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

fig, axs = plt.subplots(2, 2, constrained_layout=True)
for ax in axs.flatten():
    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)
受约束的布局参考线

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.flatten():
    example_plot(ax)
受约束的布局参考线

与网格规范一起使用

约束布局用于 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)
受约束的布局参考线

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

fig = plt.figure()

gs0 = fig.