Saya telah menghabiskan terlalu lama meneliti bagaimana mendapatkan dua subplot untuk berbagi sumbu y yang sama dengan satu colorbar bersama antara keduanya di Matplotlib.
Apa yang terjadi adalah ketika saya memanggil colorbar()
fungsi di salah satu subplot1
atau subplot2
, itu akan menskalakan plot sedemikian rupa sehingga colorbar ditambah plot akan muat di dalam kotak pembatas 'subplot', menyebabkan dua plot berdampingan menjadi dua sangat berbeda. ukuran.
Untuk menyiasatinya, saya mencoba membuat subplot ketiga yang kemudian saya retas agar tidak ada plot dengan hanya hadiah colorbar. Satu-satunya masalah adalah, sekarang ketinggian dan lebar kedua plot tidak merata, dan saya tidak tahu bagaimana membuatnya terlihat baik-baik saja.
Ini kode saya:
from __future__ import division
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import patches
from matplotlib.ticker import NullFormatter
# SIS Functions
TE = 1 # Einstein radius
g1 = lambda x,y: (TE/2) * (y**2-x**2)/((x**2+y**2)**(3/2))
g2 = lambda x,y: -1*TE*x*y / ((x**2+y**2)**(3/2))
kappa = lambda x,y: TE / (2*np.sqrt(x**2+y**2))
coords = np.linspace(-2,2,400)
X,Y = np.meshgrid(coords,coords)
g1out = g1(X,Y)
g2out = g2(X,Y)
kappaout = kappa(X,Y)
for i in range(len(coords)):
for j in range(len(coords)):
if np.sqrt(coords[i]**2+coords[j]**2) <= TE:
g1out[i][j]=0
g2out[i][j]=0
fig = plt.figure()
fig.subplots_adjust(wspace=0,hspace=0)
# subplot number 1
ax1 = fig.add_subplot(1,2,1,aspect='equal',xlim=[-2,2],ylim=[-2,2])
plt.title(r"$\gamma_{1}$",fontsize="18")
plt.xlabel(r"x ($\theta_{E}$)",fontsize="15")
plt.ylabel(r"y ($\theta_{E}$)",rotation='horizontal',fontsize="15")
plt.xticks([-2.0,-1.5,-1.0,-0.5,0,0.5,1.0,1.5])
plt.xticks([-2.0,-1.5,-1.0,-0.5,0,0.5,1.0,1.5])
plt.imshow(g1out,extent=(-2,2,-2,2))
plt.axhline(y=0,linewidth=2,color='k',linestyle="--")
plt.axvline(x=0,linewidth=2,color='k',linestyle="--")
e1 = patches.Ellipse((0,0),2,2,color='white')
ax1.add_patch(e1)
# subplot number 2
ax2 = fig.add_subplot(1,2,2,sharey=ax1,xlim=[-2,2],ylim=[-2,2])
plt.title(r"$\gamma_{2}$",fontsize="18")
plt.xlabel(r"x ($\theta_{E}$)",fontsize="15")
ax2.yaxis.set_major_formatter( NullFormatter() )
plt.axhline(y=0,linewidth=2,color='k',linestyle="--")
plt.axvline(x=0,linewidth=2,color='k',linestyle="--")
plt.imshow(g2out,extent=(-2,2,-2,2))
e2 = patches.Ellipse((0,0),2,2,color='white')
ax2.add_patch(e2)
# subplot for colorbar
ax3 = fig.add_subplot(1,1,1)
ax3.axis('off')
cbar = plt.colorbar(ax=ax2)
plt.show()
sumber
vmin
danvmax
argumen sangat penting. Mereka mengontrol rentang warna setiap subplot. Jika Anda memiliki data nyata, Anda mungkin perlu melewati ini untuk menemukan nilai min dan maks terlebih dahulu.Anda dapat menyederhanakan kode Joe Kington menggunakan
ax
parameterfigure.colorbar()
dengan daftar sumbu. Dari dokumentasi :sumber
fig.colorbar(im, ax=axes.ravel().tolist())
. Jika Anda menghilangkanax=axes.ravel().tolist()
, bilah warna akan ditempatkan dalam satu subplot.Solusi ini tidak memerlukan penyesuaian lokasi sumbu atau ukuran bilah warna secara manual, bekerja dengan tata letak multi-baris dan satu-baris, dan bekerja dengan
tight_layout()
. Ini diadaptasi dari contoh galeri , menggunakanImageGrid
dari AxesGrid Toolbox matplotlib .sumber
thecb = ax.cax.colorbar(im)
. Maka Anda dapat melakukanthecb.set_label_text("foo")
Menggunakannya
make_axes
bahkan lebih mudah dan memberikan hasil yang lebih baik. Ini juga menyediakan kemungkinan untuk menyesuaikan posisi bilah warna. Perhatikan juga opsisubplots
untuk berbagi sumbu x dan y.sumber
nrows=1
, colorbar menjadi lebih besar dari subplot lagi.Sebagai seorang pemula yang tersandung di utas ini, saya ingin menambahkan adaptasi python-for-dummies dari abevieiramota jawaban yang sangat rapi (karena saya pada level itu saya harus mencari 'ravel' untuk mencari tahu apa kode mereka sedang dilakukan):
Apalagi pythonic, lebih mudah bagi noobs seperti saya untuk melihat apa yang sebenarnya terjadi di sini.
sumber
Seperti yang ditunjukkan dalam jawaban lain, idenya biasanya untuk menentukan sumbu untuk tempat tinggal colorbar. Ada berbagai cara untuk melakukannya; salah satu yang belum disebutkan adalah untuk secara langsung menentukan sumbu colorbar pada pembuatan subplot dengan
plt.subplots()
. Keuntungannya adalah bahwa posisi sumbu tidak perlu diatur secara manual dan dalam semua kasus dengan aspek otomatis, colorbar akan persis sama tingginya dengan subplot. Bahkan dalam banyak kasus di mana gambar digunakan hasilnya akan memuaskan seperti yang ditunjukkan di bawah ini.Saat menggunakan
plt.subplots()
, penggunaangridspec_kw
argumen memungkinkan untuk membuat sumbu colorbar jauh lebih kecil dari sumbu lainnya.Contoh:
Ini bekerja dengan baik, jika aspek plot diotomatiskan atau gambar menyusut karena aspek mereka dalam arah lebar (seperti di atas). Namun, jika gambar lebih luas dari tinggi, hasilnya akan terlihat sebagai berikut, yang mungkin tidak diinginkan.
Solusi untuk memperbaiki ketinggian colorbar dengan ketinggian subplot adalah dengan menggunakan
mpl_toolkits.axes_grid1.inset_locator.InsetPosition
untuk mengatur sumbu colorbar relatif terhadap sumbu subplot gambar.sumber
ax = fig.add_subplot()
? Saya bertanya karena saya tidak tahu cara menggunakannya dengan basemap.GridSpec
keadd_subplot()
dalam hal itu.Solusi menggunakan daftar sumbu oleh abevieiramota bekerja sangat baik hingga Anda hanya menggunakan satu baris gambar, seperti yang ditunjukkan dalam komentar. Menggunakan rasio aspek yang masuk akal untuk
figsize
membantu, tetapi masih jauh dari sempurna. Sebagai contoh:Fungsi colorbar menyediakan
shrink
parameter yang merupakan faktor penskalaan untuk ukuran sumbu colorbar. Itu memang membutuhkan beberapa percobaan dan kesalahan manual. Sebagai contoh:sumber
Untuk menambahkan jawaban sempurna @ abevieiramota, Anda bisa mendapatkan euqivalent dari tight_layout dengan constrained_layout. Anda masih akan mendapatkan celah horizontal yang besar jika Anda menggunakan
imshow
alih-alihpcolormesh
karena rasio aspek 1: 1 yang dikenakan olehimshow
.sumber
Saya perhatikan bahwa hampir setiap solusi yang diposting terlibat
ax.imshow(im, ...)
dan tidak menormalkan warna yang ditampilkan ke colorbar untuk beberapa subfigures. Theim
mappable diambil dari contoh terakhir, tetapi bagaimana jika nilai-nilai dari beberapaim
-s berbeda? (Saya mengasumsikan pemetaan ini diperlakukan dengan cara yang sama dengan contour-set dan surface-set.) Saya punya contoh menggunakan plot permukaan 3d di bawah ini yang membuat dua colorbars untuk subplot 2x2 (satu colorbar per satu baris ). Meskipun pertanyaannya secara eksplisit meminta pengaturan yang berbeda, saya pikir contoh ini membantu menjelaskan beberapa hal. Saya belum menemukan cara untuk melakukan ini menggunakanplt.subplots(...)
karena kapak 3D sayangnya.Kalau saja saya bisa memposisikan colorbars dengan cara yang lebih baik ... (Mungkin ada cara yang jauh lebih baik untuk melakukan ini, tetapi setidaknya seharusnya tidak terlalu sulit untuk diikuti.)
sumber
im
s berbeda, mereka tidak boleh menggunakan colorbar yang sama, jadi pertanyaan awal tidak akan benar-benar berlakuTopik ini dibahas dengan baik tetapi saya masih ingin mengusulkan pendekatan lain dalam filosofi yang sedikit berbeda.
Pengaturannya sedikit lebih rumit, tetapi memungkinkan (menurut saya) sedikit lebih fleksibel. Misalnya, seseorang dapat bermain dengan rasio masing-masing subplot / colorbar masing-masing:
sumber