Matplotlib进阶教程:布局讲解
在后臺(tái)回復(fù)【閱讀書籍】
即可獲取python相關(guān)電子書~
Hi,我是山月。
今天來給大家介紹下Matplotlib的布局部分~
01
自定義圖形布局
可以創(chuàng)建axes的網(wǎng)格狀組合的方法:
1)subplots()
用于創(chuàng)建圖形和axes的主要函數(shù)。它類似于 matplotlib.pyplot.subplot(),但會(huì)同時(shí)創(chuàng)建并放置圖形上的所有axes。
2)GridSpec
指定將放置子圖的網(wǎng)格幾何形狀。要設(shè)置網(wǎng)格的行數(shù)和列數(shù),也可調(diào)整子圖的布局參數(shù)(如left、right等)。
3)SubplotSpec
在給定的 GridSpec 中指定子圖的位置。
4)subplot2grid()
是與 subplot() 類似的輔助函數(shù),但使用從 0 開始的索引并讓 subplot 占據(jù)多個(gè)單元格。
1、入門指南
使用 subplots() 創(chuàng)建一個(gè) 2×2 網(wǎng)格非常簡(jiǎn)單,它會(huì)返回一個(gè) Figure 實(shí)例和一個(gè) Axes 對(duì)象數(shù)組。
import?matplotlib.pyplot?as?pltfig1,?f1_axes?=?plt.subplots(ncols=2,?nrows=2,?constrained_layout=True)plt.show()效果:
使用gridspec 實(shí)現(xiàn)相同的效果會(huì)過于冗長(zhǎng):
先分別創(chuàng)建figure和GridSpec實(shí)例,然后將 gridspec 實(shí)例的元素傳遞給 add_subplot() 方法以創(chuàng)建軸對(duì)象。
gridspec元素的訪問方式與 numpy 數(shù)組相同。
import?matplotlib.pyplot?as?plt import?matplotlib.gridspec?as?gridspecfig2?=?plt.figure(constrained_layout=True) spec2?=?gridspec.GridSpec(ncols=2,?nrows=2,?figure=fig2) f2_ax1?=?fig2.add_subplot(spec2[0,?0]) f2_ax2?=?fig2.add_subplot(spec2[0,?1]) f2_ax3?=?fig2.add_subplot(spec2[1,?0]) f2_ax4?=?fig2.add_subplot(spec2[1,?1])plt.show()gridspec 的強(qiáng)大之處在于能夠創(chuàng)建跨行和列的子圖。注意用于選擇每個(gè)子圖將占據(jù)的gridspec部分的 Numpy 切片語法。
我們也可以使用 Figure.add_gridspec方法創(chuàng)建不同寬度的子圖:
import?matplotlib.pyplot?as?pltfig3?=?plt.figure(constrained_layout=True) gs?=?fig3.add_gridspec(3,?3) f3_ax1?=?fig3.add_subplot(gs[0,?:]) f3_ax1.set_title('gs[0,?:]') f3_ax2?=?fig3.add_subplot(gs[1,?:-1]) f3_ax2.set_title('gs[1,?:-1]') f3_ax3?=?fig3.add_subplot(gs[1:,?-1]) f3_ax3.set_title('gs[1:,?-1]') f3_ax4?=?fig3.add_subplot(gs[-1,?0]) f3_ax4.set_title('gs[-1,?0]') f3_ax5?=?fig3.add_subplot(gs[-1,?-2]) f3_ax5.set_title('gs[-1,?-2]')plt.show()效果:
這個(gè)方法與上面的方法類似,先初始化一個(gè)統(tǒng)一的gridspec,然后使用 numpy 索引和切片為給定的子圖分配多個(gè)“單元格”。
import?matplotlib.pyplot?as?pltfig4?=?plt.figure(constrained_layout=True) spec4?=?fig4.add_gridspec(ncols=2,?nrows=2) anno_opts?=?dict(xy=(0.5,?0.5),?xycoords='axes?fraction',va='center',?ha='center')f4_ax1?=?fig4.add_subplot(spec4[0,?0]) f4_ax1.annotate('GridSpec[0,?0]',?**anno_opts) fig4.add_subplot(spec4[0,?1]).annotate('GridSpec[0,?1:]',?**anno_opts) fig4.add_subplot(spec4[1,?0]).annotate('GridSpec[1:,?0]',?**anno_opts) fig4.add_subplot(spec4[1,?1]).annotate('GridSpec[1:,?1:]',?**anno_opts)plt.show()效果:
另一種方法是使用 width_ratios 和 height_ratios 參數(shù),這些關(guān)鍵字參數(shù)是數(shù)字列表。
請(qǐng)注意,絕對(duì)值是沒有意義的,只有它們的相對(duì)比率很重要。
這意味著在同樣寬的圖中width_ratios=[2, 4, 8] 等效于 width_ratios=[1, 2, 4]。
import?matplotlib.pyplot?as?pltfig5?=?plt.figure(constrained_layout=True) widths?=?[2,?3,?1.5] heights?=?[1,?3,?2] spec5?=?fig5.add_gridspec(ncols=3,?nrows=3,?width_ratios=widths,height_ratios=heights) for?row?in?range(3):for?col?in?range(3):ax?=?fig5.add_subplot(spec5[row,?col])label?=?'Width:?{}\nHeight:?{}'.format(widths[col],?heights[row])ax.annotate(label,?(0.1,?0.5),?xycoords='axes?fraction',?va='center')plt.show()效果:
學(xué)習(xí)使用 width_ratios 和 height_ratios 特別有用,因?yàn)轫敿?jí)函數(shù) subplots() 在 gridspec_kw 參數(shù)中接受它們。
就此而言,GridSpec 接受的任何參數(shù)都可以通過 gridspec_kw 參數(shù)傳遞給 subplots()。
在不直接使用 gridspec 實(shí)例的情況下重新創(chuàng)建上一個(gè)圖:
import?matplotlib.pyplot?as?pltwidths?=?[2,?3,?1.5] heights?=?[1,?3,?2]gs_kw?=?dict(width_ratios=widths,?height_ratios=heights) fig6,?f6_axes?=?plt.subplots(ncols=3,?nrows=3,?constrained_layout=True,gridspec_kw=gs_kw) for?r,?row?in?enumerate(f6_axes):for?c,?ax?in?enumerate(row):label?=?'Width:?{}\nHeight:?{}'.format(widths[c],?heights[r])ax.annotate(label,?(0.1,?0.5),?xycoords='axes?fraction',?va='center')plt.show()subplots 和 get_gridspec 方法可以組合使用,因?yàn)橛袝r(shí)使用 subplots 制作子圖更方便。
import?matplotlib.pyplot?as?pltfig7,?f7_axs?=?plt.subplots(ncols=3,?nrows=3) gs?=?f7_axs[1,?2].get_gridspec() #?移除下面的軸 for?ax?in?f7_axs[1:,?-1]:ax.remove() axbig?=?fig7.add_subplot(gs[1:,?-1]) axbig.annotate('Big?Axes?\nGridSpec[1:,?-1]',?(0.1,?0.5),xycoords='axes?fraction',?va='center')fig7.tight_layout()plt.show()效果:
2、微調(diào)Gridspec 布局
當(dāng)使用 GridSpec 時(shí),你可以調(diào)整用 GridSpec 創(chuàng)建的子圖的布局參數(shù)。
請(qǐng)注意,此選項(xiàng)與 constrained_layout 或 Figure.tight_layout 不兼容。
import?matplotlib.pyplot?as?pltfig8?=?plt.figure(constrained_layout=False) gs1?=?fig8.add_gridspec(nrows=3,?ncols=3,?left=0.05,?right=0.48,?wspace=0.05) f8_ax1?=?fig8.add_subplot(gs1[:-1,?:]) f8_ax2?=?fig8.add_subplot(gs1[-1,?:-1]) f8_ax3?=?fig8.add_subplot(gs1[-1,?-1])plt.show()效果:
這類似于 subplots_adjust(),但它只影響從給定的 GridSpec 創(chuàng)建的子圖。
import?matplotlib.pyplot?as?pltfig9?=?plt.figure(constrained_layout=False) gs1?=?fig9.add_gridspec(nrows=3,?ncols=3,?left=0.05,?right=0.48,wspace=0.05) f9_ax1?=?fig9.add_subplot(gs1[:-1,?:]) f9_ax2?=?fig9.add_subplot(gs1[-1,?:-1]) f9_ax3?=?fig9.add_subplot(gs1[-1,?-1])gs2?=?fig9.add_gridspec(nrows=3,?ncols=3,?left=0.55,?right=0.98,hspace=0.05) f9_ax4?=?fig9.add_subplot(gs2[:,?:-1]) f9_ax5?=?fig9.add_subplot(gs2[:-1,?-1]) f9_ax6?=?fig9.add_subplot(gs2[-1,?-1])plt.show()效果:
3、SubplotSpec
你可以從 SubplotSpec 創(chuàng)建 GridSpec,在這種情況下,其布局參數(shù)設(shè)置為給定的 SubplotSpec 的位置。
import?matplotlib.pyplot?as?pltfig10?=?plt.figure(constrained_layout=True) gs0?=?fig10.add_gridspec(1,?2)gs00?=?gs0[0].subgridspec(2,?3) gs01?=?gs0[1].subgridspec(3,?2)for?a?in?range(2):for?b?in?range(3):fig10.add_subplot(gs00[a,?b])fig10.add_subplot(gs01[b,?a])plt.show()效果:
一個(gè)更復(fù)雜的嵌套 GridSpec 示例:
import?matplotlib.pyplot?as?plt import?numpy?as?np from?itertools?import?productdef?squiggle_xy(a,?b,?c,?d,?i=np.arange(0.0,?2*np.pi,?0.05)):return?np.sin(i*a)*np.cos(i*b),?np.sin(i*c)*np.cos(i*d)fig11?=?plt.figure(figsize=(8,?8),?constrained_layout=False)#?gridspec內(nèi)部的gridspec outer_grid?=?fig11.add_gridspec(4,?4,?wspace=0.0,?hspace=0.0)for?i?in?range(16):inner_grid?=?outer_grid[i].subgridspec(3,?3,?wspace=0.0,?hspace=0.0)a,?b?=?int(i/4)+1,?i?%?4+1for?j,?(c,?d)?in?enumerate(product(range(1,?4),?repeat=2)):ax?=?fig11.add_subplot(inner_grid[j])ax.plot(*squiggle_xy(a,?b,?c,?d))ax.set_xticks([])ax.set_yticks([])fig11.add_subplot(ax)all_axes?=?fig11.get_axes()#?只露出外面的邊框線 for?ax?in?all_axes:for?sp?in?ax.spines.values():sp.set_visible(False)if?ax.get_subplotspec().is_first_row():ax.spines['top'].set_visible(True)if?ax.get_subplotspec().is_last_row():ax.spines['bottom'].set_visible(True)if?ax.get_subplotspec().is_first_col():ax.spines['left'].set_visible(True)if?ax.get_subplotspec().is_last_col():ax.spines['right'].set_visible(True)plt.show()效果:
02
約束布局
constrained_layout 可以自動(dòng)調(diào)整子圖和裝飾(如圖例和顏色條),以便它們適合圖形窗口,同時(shí)仍盡可能保留用戶請(qǐng)求的邏輯布局。
在將axes添加到圖形之前,需要激活 constrained_layout,有兩種方法激活:
1)使用 subplots() 或 figure() 的相應(yīng)參數(shù):
plt.subplots(constrained_layout=True)2)通過 rcParams 激活:
plt.rcParams['figure.constrained_layout.use']?=?True注意事項(xiàng) :
- constrained_layout 只考慮刻度標(biāo)簽、軸標(biāo)簽、標(biāo)題和圖例。因此,其他artists可能被剪裁,也可能重疊。 
- 它假定刻度標(biāo)簽、軸標(biāo)簽和標(biāo)題所需的額外空間與軸的原始位置無關(guān)。這通常是正確的,但在極少數(shù)情況下并非如此。 
- 后端處理渲染字體的方式存在細(xì)微差別,因此結(jié)果不會(huì)是完全相同的。 
- artists添加超出axes 邊界的坐標(biāo)軸時(shí)會(huì)產(chǎn)生不一樣的布局,這可以通過使用 add_artist() 將artists直接添加到圖形中來避免。 
1、簡(jiǎn)單示例
在 Matplotlib 中,axes(包括子圖)的位置在標(biāo)準(zhǔn)化圖形坐標(biāo)中指定。
但是軸標(biāo)簽或標(biāo)題(有時(shí)甚至是刻度標(biāo)簽)可能會(huì)超出圖形區(qū)域,從而被剪裁。
import?matplotlib.pyplot?as?pltplt.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)plt.show()效果:
為了防止這種情況,可以使用 constrained_layout=True 來自動(dòng)調(diào)整圖形。
fig,?ax?=?plt.subplots(constrained_layout=True) example_plot(ax,?fontsize=24)效果:
當(dāng)你有多個(gè)子圖時(shí),你可能會(huì)看到不同軸的標(biāo)簽相互重疊。
import?matplotlib.pyplot?as?pltplt.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,?axs?=?plt.subplots(2,?2,?constrained_layout=False) for?ax?in?axs.flat:example_plot(ax)plt.show()效果:
在對(duì)plt.subplots的調(diào)用中指定 constrained_layout=True 會(huì)導(dǎo)致布局受到適當(dāng)?shù)募s束。
fig,?axs?=?plt.subplots(2,?2,?constrained_layout=True) for?ax?in?axs.flat:example_plot(ax)效果:
2、顏色條
如果你要使用 colorbar() 命令創(chuàng)建顏色條,則需要為其騰出空間,可以通過constrained_layout 自動(dòng)執(zhí)行此操作。
注意,如果你指定 use_gridspec=True,它將被忽略,因?yàn)榇诉x項(xiàng)用于通過緊湊布局。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?nparr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) #?如上所述:這使得所有pcolormesh調(diào)用一致: 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)plt.show()效果:
如果你為顏色條的 ax 參數(shù)指定axes列表(或其他可迭代容器),則 constrained_layout 將占用指定axes的空間。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?nparr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) pc_kwargs?=?{'rasterized':?True,?'cmap':?'viridis',?'norm':?norm}fig,?axs?=?plt.subplots(2,?2,?figsize=(4,?4),?constrained_layout=True) for?ax?in?axs.flat:im?=?ax.pcolormesh(arr,?**pc_kwargs) fig.colorbar(im,?ax=axs,?shrink=0.6)plt.show()效果:
如果你從axes網(wǎng)格中指定axes列表,顏色條將適當(dāng)?shù)卣加每臻g并留下間隙,但所有子圖仍將具有相同的大小。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?nparr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) pc_kwargs?=?{'rasterized':?True,?'cmap':?'viridis',?'norm':?norm}fig,?axs?=?plt.subplots(3,?3,?figsize=(4,?4),?constrained_layout=True) for?ax?in?axs.flat: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)plt.show()效果:
顏色條不會(huì)如理想中一樣是對(duì)齊的,因?yàn)榕c底部軸配對(duì)的顏色條被綁定到軸的subplotspec 。
因此當(dāng)gridspec級(jí)別的顏色條被添加時(shí),顏色條會(huì)收縮。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?nparr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) pc_kwargs?=?{'rasterized':?True,?'cmap':?'viridis',?'norm':?norm}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)plt.show()效果:
3、標(biāo)題
constrained_layout 也可以為標(biāo)題騰出空間。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?nparr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) pc_kwargs?=?{'rasterized':?True,?'cmap':?'viridis',?'norm':?norm}fig,?axs?=?plt.subplots(2,?2,?figsize=(4,?4),?constrained_layout=True) for?ax?in?axs.flat:im?=?ax.pcolormesh(arr,?**pc_kwargs) fig.colorbar(im,?ax=axs,?shrink=0.6) fig.suptitle('Big?Suptitle')plt.show()效果:
4、圖例
圖例可以放置在其父軸之外。
約束布局可以為 Axes.legend() 創(chuàng)建的圖例處理此問題,但不處理通過 Figure.legend() 創(chuàng)建的圖例。
import?matplotlib.pyplot?as?plt import?numpy?as?npfig,?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))plt.show()效果:
其實(shí)這將從子圖布局中占取空間:
import?matplotlib.pyplot?as?plt import?numpy?as?npfig,?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))plt.show()效果:
為了不讓圖例或其他artist 從子圖布局中占取空間,我們可以使用leg.set_in_layout(False)。
當(dāng)然,這意味著圖例可能會(huì)被裁剪,但可以通過調(diào)用 fig.savefig('outname.png', bbox_inches='tight') 來保存完整的圖。
注意,必須再次切換圖例的 get_in_layout 狀態(tài)才能使保存的文件正常工作。
并且如果我們希望在打印之前調(diào)整axes的大小,必須手動(dòng)觸發(fā)constrained_layout。
import?matplotlib.pyplot?as?plt import?numpy?as?npfig,?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) fig.canvas.draw() leg.set_in_layout(True) fig.set_constrained_layout(False) fig.savefig('CL01.png',?bbox_inches='tight',?dpi=100)plt.show()效果:
保存的文件如下所示:
其實(shí)更好的方法是使用 Figure.legend 提供的 legend 方法:
import?matplotlib.pyplot?as?plt import?numpy?as?npfig,?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)plt.show()5、填充和間距
對(duì)于 constrained_layout,我們?cè)诿總€(gè)軸的邊緣會(huì)設(shè)置一個(gè)填充。
此填充設(shè)置了距繪圖邊緣的距離,以及相鄰繪圖之間的最小距離。
它由函數(shù) set_constrained_layout_pads 的關(guān)鍵字參數(shù) w_pad 和 h_pad 以英寸為單位指定:
import?matplotlib.pyplot?as?pltplt.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,?axs?=?plt.subplots(2,?2,?constrained_layout=True) for?ax?in?axs.flat: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.suptitle('4.72')fig,?axs?=?plt.subplots(2,?2,?constrained_layout=True) for?ax?in?axs.flat: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.) fig.suptitle('2.72')plt.show()效果:
子圖之間的間距由 wspace 和 hspace 設(shè)置,指定為子圖組整體大小的一部分。
如果圖形的大小發(fā)生變化,那么這些空間也會(huì)按比例變化。
fig,?axs?=?plt.subplots(2,?2,?constrained_layout=True) for?ax?in?axs.flat: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)效果:
顏色條和其他子圖的wspace、hsapce是分開放置的。
顏色條和它所連接的軸之間的填充永遠(yuǎn)不會(huì)小于 w_pad (對(duì)于垂直顏色條)或 h_pad (對(duì)于水平顏色條)。
請(qǐng)注意在 colorbar 調(diào)用中參數(shù)pad 默認(rèn)的大小為0.02。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?nparr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) pc_kwargs?=?{'rasterized':?True,?'cmap':?'viridis',?'norm':?norm}fig,?axs?=?plt.subplots(2,?2,?constrained_layout=True) for?ax?in?axs.flat: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)plt.show()效果:
在上面的示例中,顏色條與繪圖的距離永遠(yuǎn)不會(huì)超過 2 pts,但如果我們希望它離圖更遠(yuǎn)一點(diǎn),我們可以將它的 pad 值指定為非零。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?nparr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) pc_kwargs?=?{'rasterized':?True,?'cmap':?'viridis',?'norm':?norm}fig,?axs?=?plt.subplots(2,?2,?constrained_layout=True) for?ax?in?axs.flat:pc?=?ax.pcolormesh(arr,?**pc_kwargs)fig.colorbar(pc,?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)plt.show()效果:
6、參數(shù)
可以在腳本或 matplotlibrc 文件中設(shè)置五個(gè)參數(shù),它們都有前綴 figure.constrained_layout:
- use:是否使用 constrained_layout,默認(rèn)為False。 
- w_pad、h_pad:圍繞axes對(duì)象填充。值為表示英寸的浮點(diǎn)數(shù),默認(rèn)值為 3./72. 英寸(3 pts) 
- wspace,hspace:子圖之間的空間。是一個(gè)浮點(diǎn)數(shù)表示被分隔的子圖寬度的一小部分,默認(rèn)值為 0.02。 
效果:
7、GridSpec方法
除subplots() 之外,constrained_layout還可適用于GridSpec() 、 add_subplot() 方法。
import?matplotlib.pyplot?as?plt import?matplotlib.gridspec?as?gridspecplt.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('') plt.rcParams['figure.constrained_layout.use']?=?Truefig?=?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)plt.show()效果:
使用 add_gridspec 和 subgridspec函數(shù)可以完成更復(fù)雜的 gridspec 布局。
import?matplotlib.pyplot?as?plt import?matplotlib.gridspec?as?gridspecplt.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('') plt.rcParams['figure.constrained_layout.use']?=?Truefig?=?plt.figure() gs0?=?fig.add_gridspec(1,?2) gs1?=?gs0[0].subgridspec(2,?1) ax1?=?fig.add_subplot(gs1[0]) ax2?=?fig.add_subplot(gs1[1])example_plot(ax1) example_plot(ax2)gs2?=?gs0[1].subgridspec(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)plt.show()效果:
如果我們希望兩個(gè)網(wǎng)格的頂部和底部對(duì)齊,那么它們需要在同一個(gè) gridspec 中:
import?matplotlib.pyplot?as?pltplt.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?=?plt.figure(constrained_layout=True) gs0?=?fig.add_gridspec(6,?2) ax1?=?fig.add_subplot(gs0[:3,?0]) ax2?=?fig.add_subplot(gs0[3:,?0]) example_plot(ax1) example_plot(ax2) ax?=?fig.add_subplot(gs0[0:2,?1]) example_plot(ax) ax?=?fig.add_subplot(gs0[2:4,?1]) example_plot(ax) ax?=?fig.add_subplot(gs0[4:,?1]) example_plot(ax)plt.show()效果:
此示例使用兩個(gè) gridspecs 使顏色條只和一組pcolors有關(guān)。
import?matplotlib.pyplot?as?plt import?matplotlib.colors?as?mcolors import?numpy?as?npplt.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('')arr?=?np.arange(100).reshape((10,?10)) norm?=?mcolors.Normalize(vmin=0.,?vmax=100.) pc_kwargs?=?{'rasterized':?True,?'cmap':?'viridis',?'norm':?norm}def?docomplicated(suptitle=None):fig?=?plt.figure(constrained_layout=True)gs0?=?fig.add_gridspec(1,?2,?figure=fig,?width_ratios=[1.,?2.])gsl?=?gs0[0].subgridspec(2,?1)gsr?=?gs0[1].subgridspec(2,?2)for?gs?in?gsl:ax?=?fig.add_subplot(gs)example_plot(ax)axs?=?[]for?gs?in?gsr:ax?=?fig.add_subplot(gs)pcm?=?ax.pcolormesh(arr,?**pc_kwargs)ax.set_xlabel('x-label')ax.set_ylabel('y-label')ax.set_title('title')axs?+=?[ax]fig.colorbar(pcm,?ax=axs)if?suptitle?is?not?None:fig.suptitle(suptitle)docomplicated()plt.show()效果:
8、手動(dòng)設(shè)置axes位置
手動(dòng)調(diào)用set_position可以設(shè)置axes位置,因此 constrained_layout 不再對(duì)其產(chǎn)生影響。
import?matplotlib.pyplot?as?pltplt.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,?axs?=?plt.subplots(1,?2) example_plot(axs[0],?fontsize=12) axs[1].set_position([0.2,?0.2,?0.4,?0.4])plt.show()效果:
如果你想在數(shù)據(jù)空間中插入axes,則需要使用 fig.execute_constrained_layout() 來手動(dòng)布局,然后在正確的位置里插入圖形。
但是,如果之后更改圖形的大小,它將無法正確定位。
同樣,如果將圖形打印到另一個(gè)后端,由于后端渲染字體的方式存在微小差異,位置也可能會(huì)略有變化。
import?matplotlib.pyplot?as?plt from?matplotlib.transforms?import?Bboxplt.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,?axs?=?plt.subplots(1,?2) example_plot(axs[0],?fontsize=12) fig.execute_constrained_layout() bb_data_ax2?=?Bbox.from_bounds(0.5,?1.,?0.2,?0.4) disp_coords?=?axs[0].transData.transform(bb_data_ax2) fig_coords_ax2?=?fig.transFigure.inverted().transform(disp_coords) bb_ax2?=?Bbox(fig_coords_ax2) ax2?=?fig.add_axes(bb_ax2)plt.show()效果:
03
緊湊布局
tight_layout 會(huì)自動(dòng)調(diào)整 subplot 參數(shù),以便 subplot(s) 適合圖形區(qū)域。
但它只檢查刻度標(biāo)簽、軸標(biāo)簽和標(biāo)題的范圍。
1、簡(jiǎn)單示例
在 matplotlib 中,axes(包括子圖)的位置在圖形坐標(biāo)中指定。
軸標(biāo)簽或標(biāo)題(有時(shí)甚至是刻度標(biāo)簽)可能會(huì)超出圖形區(qū)域,從而被剪裁。
import?matplotlib.pyplot?as?pltplt.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)plt.show()效果:
為了防止這種情況,需要調(diào)整 axes的位置。
可以使用tight_layout(),它會(huì)自動(dòng)為你執(zhí)行此操作:
fig,?ax?=?plt.subplots() example_plot(ax,?fontsize=24) plt.tight_layout()效果:
注意, matplotlib.pyplot.tight_layout() 只會(huì)在調(diào)用時(shí)才調(diào)整子圖參數(shù)。
為了在每次重繪圖形時(shí)執(zhí)行此調(diào)整,你可以調(diào)用 fig.set_tight_layout(True),或者等效地將 figure.autolayout 參數(shù)設(shè)置為 True。
當(dāng)你有多個(gè)子圖時(shí),你通常會(huì)看到不同軸的標(biāo)簽相互重疊:
import?matplotlib.pyplot?as?pltplt.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,?((ax1,?ax2),?(ax3,?ax4))?=?plt.subplots(nrows=2,?ncols=2) example_plot(ax1) example_plot(ax2) example_plot(ax3) example_plot(ax4)plt.show()效果:
tight_layout() 可以調(diào)整子圖之間的間距以最小化重疊:
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 的關(guān)鍵字參數(shù),以控制圖形邊界周圍和子圖之間的填充。
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)效果:
即使子圖的大小不同,但只要它們的網(wǎng)格格式兼容,tight_layout() 也將起作用。
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()效果:
plt.tight_layout()也適用于使用 subplot2grid() 創(chuàng)建的子圖:
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()效果:
2、GridSpe方法
tight_layout()對(duì)于GridSpec方法也適用:
import?matplotlib.pyplot?as?plt import?matplotlib.gridspec?as?gridspecplt.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?=?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)plt.show()效果:
你可以提供一個(gè)可選的 rect 參數(shù),它將指定子圖的邊界框。 rect 參數(shù)的值是標(biāo)準(zhǔn)圖形坐標(biāo),默認(rèn)為 (0, 0, 1, 1)。
import?matplotlib.pyplot?as?plt import?matplotlib.gridspec?as?gridspecplt.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?=?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])plt.show()效果:
tight_layout()也可用于具有多個(gè) gridspecs 方法的圖形:
import?matplotlib.pyplot?as?plt import?matplotlib.gridspec?as?gridspecplt.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?=?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)#?匹配兩個(gè)網(wǎng)格的頂部和底部 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()效果:
3、圖例
添加圖例:
import?matplotlib.pyplot?as?pltfig,?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()效果:
設(shè)置 leg.set_in_layout(False) 可以從邊界框計(jì)算中刪除圖例:
import?matplotlib.pyplot?as?pltfig,?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()效果:
4、AxesGrid1方法
雖然作用有限,但tight_layout()也支持 mpl_toolkits.axes_grid1:
import?matplotlib.pyplot?as?plt from?mpl_toolkits.axes_grid1?import?Gridplt.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?=?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()plt.show()效果:
5、顏色條
如果你使用 colorbar() 命令創(chuàng)建顏色條,則創(chuàng)建的顏色條是 Axes 的實(shí)例,而不是 Subplot,因此tight_layout 不起作用。
但你可以通過 gridspec 創(chuàng)建一個(gè)顏色條作為子圖。
import?matplotlib.pyplot?as?plt import?numpy?as?nparr?=?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()plt.show()效果:
另一種選擇是使用 AxesGrid1 工具包為顏色條顯式創(chuàng)建?axes。
import?matplotlib.pyplot?as?plt import?numpy?as?np from?mpl_toolkits.axes_grid1?import?make_axes_locatableplt.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()plt.show()效果:
好啦,這個(gè)部分就介紹到這~
END
您的“點(diǎn)贊”、“在看”和 “分享”是我們產(chǎn)出的動(dòng)力。
總結(jié)
以上是生活随笔為你收集整理的Matplotlib进阶教程:布局讲解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 2022年北京首店补贴及首店首发项目征集
- 下一篇: html5 上标,HTML5 Canva
