天天看點

Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

密緻布局指南

原文: Tight Layout guide 譯者: 飛龍 協定: CC BY-NC-SA 4.0

tight_layout

會自動調整子圖參數,使之填充整個圖像區域。這是個實驗特性,可能在一些情況下不工作。它僅僅檢查坐标軸标簽、刻度标簽以及标題的部分。

簡單的示例

在 matplotlib 中,軸域(包括子圖)的位置以标準化圖形坐标指定。 可能發生的是,你的軸标簽或标題(有時甚至是刻度标簽)會超出圖形區域,是以被截斷。

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)           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

為了避免它,軸域的位置需要調整。對于子圖,這可以通過調整子圖參數(

移動軸域的一條邊來給刻度标簽騰地方

)。Matplotlib v1.1 引入了一個新的指令

tight_layout()

,自動為你解決這個問題。

plt.tight_layout()           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

當你擁有多個子圖時,你會經常看到不同軸域的标簽疊在一起。

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)           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

tight_layout()

也會調整子圖之間的間隔來減少堆疊。

Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

tight_layout()

可以接受關鍵字參數

pad

w_pad

或者

h_pad

,這些參數圖像邊界和子圖之間的額外邊距。邊距以字型大小機關規定。

plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

即使子圖大小不同,

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()           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

它适用于使用

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()           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

雖然沒有徹底測試,它看起來也适用于

aspect

不為

auto

的子圖(例如帶有圖像的軸域)。

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()           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

警告

  • tight_layout()

    隻考慮刻度标簽,軸标簽和标題。 是以,其他藝術家可能被截斷并且也可能重疊。
  • 它假定刻度标簽,軸标簽和标題所需的額外空間與軸域的原始位置無關。 這通常是真的,但在罕見的情況下不是。
  • pad = 0

    将某些文本剪切幾個像素。 這可能是目前算法的錯誤或限制,并且不清楚為什麼會發生。 同時,推薦使用至少大于 0.3 的間隔。

GridSpec

一起使用

GridSpec

擁有自己的

tight_layout()

方法(pyplot API 的

tight_layout()

也能生效)。

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

import matplotlib.gridspec as gridspec

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)           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

你可以提供一個可選的

rect

參數,指定子圖所填充的邊框。 坐标必須為标準化圖形坐标,預設值為

(0, 0, 1, 1)

gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

例如,這可用于帶有多個

gridspecs

的圖形。

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)           
Matplotlib 中文使用者指南 3.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)           

雖然這應該足夠好了,調整頂部和底部可能也需要調整

hspace

。 為了更新

hspace

vspace

,我們再次使用更新後的

rect

參數調用

tight_layout()

。 注意,

rect

參數指定的區域包括刻度标簽。是以,我們将底部(正常情況下為 0)增加每個

gridspec

的底部之差。 頂部也一樣。

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)           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

AxesGrid1

雖然受限但也支援

axes_grid1

工具包

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

from mpl_toolkits.axes_grid1 import Grid
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()           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南

顔色條

如果你使用

colorbar

指令建立了顔色條,建立的顔色條是

Axes

而不是

Subplot

的執行個體,是以

tight_layout

沒有效果。在 Matplotlib v1.1 中,你可以使用

gridspec

将顔色條建立為子圖。

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, use_gridspec=True)

plt.tight_layout()           

![])

http://matplotlib.org/_images/tight_layout_guide-14.png

另一個選項是使用

AxesGrid1

工具包,顯式為顔色條建立一個軸域:

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

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

plt.tight_layout()           
Matplotlib 中文使用者指南 3.5 密緻布局指南密緻布局指南