簡體   English   中英

精確控制matplotlib中子圖的位置

[英]Precise control over subplot locations in matplotlib

我目前正在為紙制作圖形,如下所示:

在此處輸入圖片說明

上面的代碼非常接近我想要的樣子,但是我有一種強烈的感覺,我沒有以“正確的方式”執行此操作,因為它確實很容易產生,並且我的代碼充滿了各種魔術我手動調整位置的數字。 因此,我的問題是,制作這樣的情節的正確方法是什么?

這是該繪圖難以制作的重要特征:

  • 這三個子圖的長寬比由數據固定,但是圖像的分辨率並非全部相同。

  • 我希望所有三個情節都占據圖的全部高度

  • 我希望(a)和(b)靠近,因為它們共享y軸,而(c)距離較遠

  • 理想情況下,我希望頂部顏色條的頂部與三個圖像的頂部完全匹配,並且與底部顏色條的底部完全匹配。 (實際上它們並沒有完全對齊,因為我通過猜測數字並重新編譯圖像來做到這一點。)

在制作此圖時,我首先嘗試使用GridSpec ,但是我無法控制三個主要子圖之間的相對間距。 然后,我嘗試了AxisGrid工具包中的ImageGrid ,但是三張圖像之間的分辨率不同導致其表現異常。 深入研究AxesGrid,我能夠使用append_axes函數定位三個主要的子圖,但是我仍然必須手動定位三個色標。 (我手動創建了顏色條。)

我不想發布我現有的代碼,因為這是駭客和魔術數字的可怕集合。 而是我的問題是,在MatPlotLib中,有什么方法可以僅指定圖形的邏輯布局(即,上面項目符號的內容),並自動為我計算布局嗎?

這是一個可能的解決方案。 您將從圖形寬度開始(這在准備紙張時很有意義),然后使用圖形的各個方面,子圖和邊距之間的任意間距來計算遍歷。 這些公式與我在此答案中使用的公式相似。 GridSpecwidth_ratios參數可以解決不平等的方面。 然后,您得到一個圖形高度,以使子圖的高度相等。

因此,您無法避免輸入一些數字,但是它們不是“魔術”。 所有這些都與必要的數量有關,例如圖形大小的分數或平均子圖大小的分數。 由於系統是封閉的,因此更改任何數字都只會產生不同的圖形高度,但不會破壞布局。

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np; np.random.seed(42)

imgs = []
shapes = [(550,200), ( 550,205), (1100,274) ]
for shape in shapes:
    imgs.append(np.random.random(shape))

# calculate inverse aspect(width/height) for all images
inva = np.array([ img.shape[1]/float(img.shape[0]) for img in imgs])
# set width of empty column used to stretch layout
emptycol = 0.02
r = np.array([inva[0],inva[1], emptycol, inva[2], 3*emptycol, emptycol])
# set a figure width in inch
figw = 8
# border, can be set independently of all other quantities
left = 0.1; right=1-left
bottom=0.1; top=1-bottom
# wspace (=average relative space between subplots)
wspace = 0.1
#calculate scale
s = figw*(right-left)/(len(r)+(len(r)-1)*wspace) 
# mean aspect
masp = len(r)/np.sum(r)
#calculate figheight
figh = s*masp/float(top-bottom)


gs = gridspec.GridSpec(3,len(r), width_ratios=r)

fig = plt.figure(figsize=(figw,figh))
plt.subplots_adjust(left, bottom, right, top, wspace)

ax1 = plt.subplot(gs[:,0])
ax2 = plt.subplot(gs[:,1])
ax2.set_yticks([])

ax3 = plt.subplot(gs[:,3])
ax3.yaxis.tick_right()
ax3.yaxis.set_label_position("right")

cax1 = plt.subplot(gs[0,5])
cax2 = plt.subplot(gs[1,5])
cax3 = plt.subplot(gs[2,5])


im1 = ax1.imshow(imgs[0], cmap="viridis")
im2 = ax2.imshow(imgs[1], cmap="plasma")
im3 = ax3.imshow(imgs[2], cmap="RdBu")

fig.colorbar(im1, ax=ax1, cax=cax1)
fig.colorbar(im2, ax=ax2, cax=cax2)
fig.colorbar(im3, ax=ax3, cax=cax3)

ax1.set_title("image title")
ax1.set_xlabel("xlabel")
ax1.set_ylabel("ylabel")

plt.show()

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM