笔记
单击此处 下载完整的示例代码
紧凑的布局指南#
如何使用紧凑的布局来干净地适合你的图形。
tight_layout自动调整 subplot 参数,以便 subplot(s) 适合图形区域。这是一项实验性功能,在某些情况下可能不起作用。它只检查刻度标签、轴标签和标题的范围。
一个紧凑布局的替代方案是constrained_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)
为了防止这种情况,需要调整轴的位置。对于子图,这可以通过使用 调整子图参数来手动完成Figure.subplots_adjust
。Figure.tight_layout
自动执行此操作。
fig, ax = plt.subplots()
example_plot(ax, fontsize=24)
plt.tight_layout()
请注意,它matplotlib.pyplot.tight_layout()
只会在调用时调整子图参数。为了在每次重绘图形时执行此调整,您可以调用fig.set_tight_layout(True)
,或者等效地,将rcParams["figure.autolayout"]
(默认值:)设置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)
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()
tight_layout()
可以采用
pad、w_pad和h_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)
tight_layout()
即使子图的大小不同,只要它们的网格规范兼容,它也可以工作。在下面的示例中,ax1和ax2是 2x2 网格的子图,而ax3是 1x2 网格的子图。
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()
它适用于使用创建的子图
subplot2grid()
。通常,从 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()
虽然没有经过彻底测试,但它似乎适用于 aspect != "auto" 的子图(例如,带有图像的轴)。
arr = np.arange(100).reshape((10, 10))
plt.close('all')
fig = plt.figure(figsize=(5, 4))
ax = plt.subplot()
im = ax.imshow(arr, interpolation="none")
plt.tight_layout()
注意事项#
tight_layout
默认情况下考虑轴上的所有艺术家。要从布局计算中删除艺术家,您可以调用Artist.set_in_layout
.tight_layout
假设艺术家所需的额外空间与坐标轴的原始位置无关。这通常是正确的,但在极少数情况下并非如此。pad=0
可以将一些文本裁剪几个像素。这可能是当前算法的错误或限制,尚不清楚为什么会发生。同时,推荐使用大于 0.3 的焊盘。
与 GridSpec 一起使用#
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)
您可以提供一个可选的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.0])
但是,我们不建议将其用于手动构建更复杂的布局,例如在图的左侧和右侧有一个 GridSpec。对于这些用例,应该利用Nested Gridspecs或Figure subfigures 。
图例和注释#
在 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()
但是,有时这不是我们所希望的(在使用 时经常如此
)。为了从边界框计算中删除图例,我们只需设置它的边界,图例将被忽略。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()
与 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()
彩条#
如果您使用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()
另一种选择是使用 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()
脚本总运行时间:(0分5.470秒)