紧密布局指南

如何使用紧凑的布局,使图形中的绘图更清晰。

tight_layout 自动调整子批次参数,使子批次适合图形区域。这是一个实验特性,在某些情况下可能不起作用。它只检查刻度线标签、轴标签和标题的范围。

替代 tight_layoutconstrained_layout .

简单实例

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

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['savefig.facecolor'] = "0.8"


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

    ax.locator_params(nbins=3)
    ax.set_xlabel('x-label', fontsize=fontsize)
    ax.set_ylabel('y-label', fontsize=fontsize)
    ax.set_title('Title', fontsize=fontsize)

plt.close('all')
fig, ax = plt.subplots()
example_plot(ax, fontsize=24)
Title

为了防止这种情况发生,需要调整轴的位置。对于子批次,这可以通过调整子批次参数来完成。 (移动轴的边缘,为刻度标签留出空间 ). Matplotlib v1.1介绍 Figure.tight_layout 这对你来说是自动的。

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

注意 matplotlib.pyplot.tight_layout() 仅在调用子批次参数时进行调整。为了在每次重新绘制图形时执行此调整,可以调用 fig.set_tight_layout(True) ,或者,等价地,set rcParams["figure.autolayout"] (default: False) 到 True .

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

plt.close('all')

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
Title, Title, Title, Title

tight_layout() 还将调整子批次之间的间距,以最小化重叠。

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
plt.tight_layout()
Title, Title, Title, Title

tight_layout() 不能接受的关键字参数 padw_padh_pad . 这些控件控制图形边框周围和子图块之间的额外填充。垫子是以字体大小的分数指定的。

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
Title, Title, Title, Title

tight_layout() 即使子批次的大小不同,只要它们的网格规范兼容,也可以工作。在下面的示例中, ax1ax2 是2x2网格的子块,而 ax3 是1×2网格。

plt.close('all')
fig = plt.figure()

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

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)

plt.tight_layout()
Title, Title, Title

它与创建的子批次一起使用 subplot2grid() . 一般来说,从gridspec创建的子批次 (使用GRIDSPEC和其他功能自定义图形布局 )会奏效的。

plt.close('all')
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)

plt.tight_layout()
Title, Title, Title, Title

虽然没有彻底测试,但它似乎适用于具有方面的子批次!=“自动”(例如,带图像的轴)。

arr = np.arange(100).reshape((10, 10))

plt.close('all')
fig = plt.figure(figsize=(5, 4))

ax = plt.subplot(111)
im = ax.imshow(arr, interpolation="none")

plt.tight_layout()
tight layout guide

告诫

  • tight_layout 默认情况下,考虑轴上的所有艺术家。要从布局计算中删除艺术家,可以调用 Artist.set_in_layout .
  • tight_layout 假定艺术家所需的额外空间与轴的原始位置无关。这通常是正确的,但也有少数情况并非如此。
  • pad=0 可以将一些文本剪辑几个像素。这可能是一个错误或当前算法的限制,不清楚为什么会发生这种情况。同时,建议使用大于0.3的衬垫。

与网格规范一起使用

gridspec有自己的 GridSpec.tight_layout 方法(Pyplot API pyplot.tight_layout 还工作)。

import matplotlib.gridspec as gridspec

plt.close('all')
fig = plt.figure()

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

example_plot(ax1)
example_plot(ax2)

gs1.tight_layout(fig)
Title, Title

您可以提供一个可选的 rect 参数,该参数指定子批次将适合的边界框。坐标必须为标准化图形坐标,默认值为(0、0、1、1)。

fig = plt.figure()

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

example_plot(ax1)
example_plot(ax2)

gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
Title, Title

例如,这可以用于具有多个网格规格的图形。

fig = plt.figure()

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

example_plot(ax1)
example_plot(ax2)

gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])

gs2 = gridspec.GridSpec(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)

gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)

# We may try to match the top and bottom of two grids ::
top = min(gs1.top, gs2.top)
bottom = max(gs1.bottom, gs2.bottom)

gs1.update(top=top, bottom=bottom)
gs2.update(top=top, bottom=bottom)
plt.show()
Title, Title

出:

/pb1/rst_repos/git/matplotlib/tutorials/intermediate/tight_layout_guide.py:227: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)

虽然这应该足够好,但调整顶部和底部可能也需要调整hspace。要更新hspace和vspace,我们调用 GridSpec.tight_layout 再次更新rect参数。请注意,rect参数指定了包含TickLabels等的区域。因此,我们将通过 底部 从每个网格规范的上方和底部。顶部也是一样。

fig = plt.gcf()

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

example_plot(ax1)
example_plot(ax2)

gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])

gs2 = gridspec.GridSpec(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)

gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)

top = min(gs1.top, gs2.top)
bottom = max(gs1.bottom, gs2.bottom)

gs1.update(top=top, bottom=bottom)
gs2.update(top=top, bottom=bottom)

top = min(gs1.top, gs2.top)
bottom = max(gs1.bottom, gs2.bottom)

gs1.tight_layout(fig, rect=[None, 0 + (bottom-gs1.bottom),
                            0.5, 1 - (gs1.top-top)])
gs2.tight_layout(fig, rect=[0.5, 0 + (bottom-gs2.bottom),
                            None, 1 - (gs2.top-top)],
                 h_pad=0.5)
Title, Title

出:

/pb1/rst_repos/git/matplotlib/tutorials/intermediate/tight_layout_guide.py:267: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)
/pb1/rst_repos/git/matplotlib/tutorials/intermediate/tight_layout_guide.py:279: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  0.5, 1 - (gs1.top-top)])
/pb1/rst_repos/git/matplotlib/tutorials/intermediate/tight_layout_guide.py:282: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  h_pad=0.5)

图例和注释

Matplotlib 2.2之前,图例和注释从决定布局的边界框计算中排除。随后,这些艺术家被加入到计算中,但有时不希望包括他们。例如,在这种情况下,最好将轴稍微缩小一点,以便为图例留出空间:

fig, ax = plt.subplots(figsize=(4, 3))
lines = ax.plot(range(10), label='A simple plot')
ax.legend(bbox_to_anchor=(0.7, 0.5), loc='center left',)
fig.tight_layout()
plt.show()
tight layout guide

然而,有时这是不需要的(经常在使用时 fig.savefig('outname.png', bbox_inches='tight') )为了从边界框计算中删除图例,我们只需设置其边界。 leg.set_in_layout(False) 而这个传说将被忽略。

fig, ax = plt.subplots(figsize=(4, 3))
lines = ax.plot(range(10), label='B simple plot')
leg = ax.legend(bbox_to_anchor=(0.7, 0.5), loc='center left',)
leg.set_in_layout(False)
fig.tight_layout()
plt.show()
tight layout guide

与axesgrid1一起使用

虽然有限, mpl_toolkits.axes_grid1 也支持。

from mpl_toolkits.axes_grid1 import Grid

plt.close('all')
fig = plt.figure()
grid = Grid(fig, rect=111, nrows_ncols=(2, 2),
            axes_pad=0.25, label_mode='L',
            )

for ax in grid:
    example_plot(ax)
ax.title.set_visible(False)

plt.tight_layout()
Title, Title, Title, Title

测控条

如果用 Figure.colorbar ,只要父轴也是子图,创建的颜色条就绘制在子图中,因此 Figure.tight_layout 会工作。

plt.close('all')
arr = np.arange(100).reshape((10, 10))
fig = plt.figure(figsize=(4, 4))
im = plt.imshow(arr, interpolation="none")

plt.colorbar(im)

plt.tight_layout()
tight layout guide

另一个选项是使用axesgrid1工具包显式创建颜色条的轴。

from mpl_toolkits.axes_grid1 import make_axes_locatable

plt.close('all')
arr = np.arange(100).reshape((10, 10))
fig = plt.figure(figsize=(4, 4))
im = plt.imshow(arr, interpolation="none")

divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", "5%", pad="3%")
plt.colorbar(im, cax=cax)

plt.tight_layout()
tight layout guide

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

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