Skip to content

Commit de800c4

Browse files
committed
3.4
1 parent dab8b6f commit de800c4

File tree

1 file changed

+257
-0
lines changed

1 file changed

+257
-0
lines changed

3.4.md

+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
# 密致布局指南
2+
3+
> 原文:[Tight Layout guide](http://matplotlib.org/users/tight_layout_guide.html)
4+
5+
> 译者:[飞龙](https://github.com/)
6+
7+
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
8+
9+
`tight_layout`会自动调整子图参数,使之填充整个图像区域。这是个实验特性,可能在一些情况下不工作。它仅仅检查坐标轴标签、刻度标签以及标题的部分。
10+
11+
## 简单的示例
12+
13+
在 matplotlib 中,轴域(包括子图)的位置以标准化图形坐标指定。 可能发生的是,你的轴标签或标题(有时甚至是刻度标签)会超出图形区域,因此被截断。
14+
15+
```py
16+
plt.rcParams['savefig.facecolor'] = "0.8"
17+
18+
def example_plot(ax, fontsize=12):
19+
ax.plot([1, 2])
20+
ax.locator_params(nbins=3)
21+
ax.set_xlabel('x-label', fontsize=fontsize)
22+
ax.set_ylabel('y-label', fontsize=fontsize)
23+
ax.set_title('Title', fontsize=fontsize)
24+
25+
plt.close('all')
26+
fig, ax = plt.subplots()
27+
example_plot(ax, fontsize=24)
28+
```
29+
30+
![](http://matplotlib.org/_images/tight_layout_guide-1.png)
31+
32+
为了避免它,轴域的位置需要调整。对于子图,这可以通过调整子图参数([移动轴域的一条边来给刻度标签腾地方](http://matplotlib.org/faq/howto_faq.html#howto-subplots-adjust))。Matplotlib v1.1 引入了一个新的命令` tight_layout()`,自动为你解决这个问题。
33+
34+
```py
35+
plt.tight_layout()
36+
```
37+
38+
![](http://matplotlib.org/_images/tight_layout_guide-2.png)
39+
40+
当你拥有多个子图时,你会经常看到不同轴域的标签叠在一起。
41+
42+
```py
43+
plt.close('all')
44+
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
45+
example_plot(ax1)
46+
example_plot(ax2)
47+
example_plot(ax3)
48+
example_plot(ax4)
49+
```
50+
51+
![](http://matplotlib.org/_images/tight_layout_guide-3.png)
52+
53+
`tight_layout()`也会调整子图之间的间隔来减少堆叠。
54+
55+
![](http://matplotlib.org/_images/tight_layout_guide-4.png)
56+
57+
`tight_layout()`可以接受关键字参数`pad``w_pad`或者`h_pad`,这些参数图像边界和子图之间的额外边距。边距以字体大小单位规定。
58+
59+
```py
60+
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
61+
```
62+
63+
![](http://matplotlib.org/_images/tight_layout_guide-5.png)
64+
65+
即使子图大小不同,`tight_layout()`也能够工作,只要网格的规定的兼容的。在下面的例子中,`ax1``ax2`是 2x2 网格的子图,但是`ax3`是 1x2 网格。
66+
67+
```py
68+
plt.close('all')
69+
fig = plt.figure()
70+
71+
ax1 = plt.subplot(221)
72+
ax2 = plt.subplot(223)
73+
ax3 = plt.subplot(122)
74+
75+
example_plot(ax1)
76+
example_plot(ax2)
77+
example_plot(ax3)
78+
79+
plt.tight_layout()
80+
```
81+
82+
![](http://matplotlib.org/_images/tight_layout_guide-6.png)
83+
84+
它适用于使用`subplot2grid()`创建的子图。 一般来说,从`gridspec`[使用`GridSpec`自定义子布局的位置](http://matplotlib.org/users/gridspec.html#gridspec-guide))创建的子图也能正常工作。
85+
86+
```py
87+
plt.close('all')
88+
fig = plt.figure()
89+
90+
ax1 = plt.subplot2grid((3, 3), (0, 0))
91+
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
92+
ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
93+
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
94+
95+
example_plot(ax1)
96+
example_plot(ax2)
97+
example_plot(ax3)
98+
example_plot(ax4)
99+
100+
plt.tight_layout()
101+
```
102+
103+
![](http://matplotlib.org/_images/tight_layout_guide-7.png)
104+
105+
虽然没有彻底测试,它看起来也适用于`aspect`不为`auto`的子图(例如带有图像的轴域)。
106+
107+
```py
108+
arr = np.arange(100).reshape((10,10))
109+
110+
plt.close('all')
111+
fig = plt.figure(figsize=(5,4))
112+
113+
ax = plt.subplot(111)
114+
im = ax.imshow(arr, interpolation="none")
115+
116+
plt.tight_layout()
117+
```
118+
119+
![](http://matplotlib.org/_images/tight_layout_guide-8.png)
120+
121+
## 警告
122+
123+
+ `tight_layout()`只考虑刻度标签,轴标签和标题。 因此,其他 Artist 可能被截断并且也可能重叠。
124+
+ 它假定刻度标签,轴标签和标题所需的额外空间与轴域的原始位置无关。 这通常是真的,但在罕见的情况下不是。
125+
+ `pad = 0`将某些文本剪切几个像素。 这可能是当前算法的错误或限制,并且不清楚为什么会发生。 同时,推荐使用至少大于 0.3 的间隔。
126+
127+
## `GridSpec`一起使用
128+
129+
`GridSpec`拥有自己的`tight_layout()`方法(pyplot API 的`tight_layout()`也能生效)。
130+
131+
```py
132+
133+
plt.close('all')
134+
fig = plt.figure()
135+
136+
import matplotlib.gridspec as gridspec
137+
138+
gs1 = gridspec.GridSpec(2, 1)
139+
ax1 = fig.add_subplot(gs1[0])
140+
ax2 = fig.add_subplot(gs1[1])
141+
142+
example_plot(ax1)
143+
example_plot(ax2)
144+
145+
gs1.tight_layout(fig)
146+
```
147+
148+
![](http://matplotlib.org/_images/tight_layout_guide-9.png)
149+
150+
你可以提供一个可选的`rect`参数,指定子图所填充的边框。 坐标必须为标准化图形坐标,默认值为`(0, 0, 1, 1)`
151+
152+
```py
153+
gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
154+
```
155+
156+
![](http://matplotlib.org/_images/tight_layout_guide-10.png)
157+
158+
例如,这可用于带有多个`gridspecs`的图形。
159+
160+
```py
161+
gs2 = gridspec.GridSpec(3, 1)
162+
163+
for ss in gs2:
164+
ax = fig.add_subplot(ss)
165+
example_plot(ax)
166+
ax.set_title("")
167+
ax.set_xlabel("")
168+
169+
ax.set_xlabel("x-label", fontsize=12)
170+
171+
gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)
172+
```
173+
174+
![](http://matplotlib.org/_images/tight_layout_guide-11.png)
175+
176+
我们可以尝试匹配两个网格的顶部和底部。
177+
178+
```py
179+
top = min(gs1.top, gs2.top)
180+
bottom = max(gs1.bottom, gs2.bottom)
181+
182+
gs1.update(top=top, bottom=bottom)
183+
gs2.update(top=top, bottom=bottom)
184+
```
185+
186+
虽然这应该足够好了,调整顶部和底部可能也需要调整`hspace`。 为了更新`hspace``vspace`,我们再次使用更新后的`rect`参数调用`tight_layout()`。 注意,`rect`参数指定的区域包括刻度标签。因此,我们将底部(正常情况下为 0)增加每个`gridspec`的底部之差。 顶部也一样。
187+
188+
189+
```py
190+
top = min(gs1.top, gs2.top)
191+
bottom = max(gs1.bottom, gs2.bottom)
192+
193+
gs1.tight_layout(fig, rect=[None, 0 + (bottom-gs1.bottom),
194+
0.5, 1 - (gs1.top-top)])
195+
gs2.tight_layout(fig, rect=[0.5, 0 + (bottom-gs2.bottom),
196+
None, 1 - (gs2.top-top)],
197+
h_pad=0.5)
198+
```
199+
200+
![](http://matplotlib.org/_images/tight_layout_guide-12.png)
201+
202+
## `AxesGrid1`一起使用
203+
204+
虽然受限但也支持`axes_grid1`工具包
205+
206+
```py
207+
plt.close('all')
208+
fig = plt.figure()
209+
210+
from mpl_toolkits.axes_grid1 import Grid
211+
grid = Grid(fig, rect=111, nrows_ncols=(2,2),
212+
axes_pad=0.25, label_mode='L',
213+
)
214+
215+
for ax in grid:
216+
example_plot(ax)
217+
ax.title.set_visible(False)
218+
219+
plt.tight_layout()
220+
```
221+
222+
![](http://matplotlib.org/_images/tight_layout_guide-13.png)
223+
224+
## 颜色条
225+
226+
如果你使用`colorbar`命令创建了颜色条,创建的颜色条是`Axes`而不是`Subplot`的实例,所以`tight_layout`没有效果。在 Matplotlib v1.1 中,你可以使用`gridspec`将颜色条创建为子图。
227+
228+
```py
229+
plt.close('all')
230+
arr = np.arange(100).reshape((10,10))
231+
fig = plt.figure(figsize=(4, 4))
232+
im = plt.imshow(arr, interpolation="none")
233+
234+
plt.colorbar(im, use_gridspec=True)
235+
236+
plt.tight_layout()
237+
```
238+
239+
![])http://matplotlib.org/_images/tight_layout_guide-14.png
240+
241+
另一个选项是使用`AxesGrid1`工具包,显式为颜色条创建一个轴域:
242+
243+
```py
244+
plt.close('all')
245+
arr = np.arange(100).reshape((10,10))
246+
fig = plt.figure(figsize=(4, 4))
247+
im = plt.imshow(arr, interpolation="none")
248+
249+
from mpl_toolkits.axes_grid1 import make_axes_locatable
250+
divider = make_axes_locatable(plt.gca())
251+
cax = divider.append_axes("right", "5%", pad="3%")
252+
plt.colorbar(im, cax=cax)
253+
254+
plt.tight_layout()
255+
```
256+
257+
![](http://matplotlib.org/_images/tight_layout_guide-15.png)

0 commit comments

Comments
 (0)