Matplotlib renk çubuğu boyutunu grafiğe uyacak şekilde ayarlama


161

Bunun gibi imshow grafiklerinde colorbar'ı grafikle aynı yükseklikte alamıyorum, gerçeğin ardından Photoshop'u kullanmıyorum. Yükseklikleri nasıl eşleştirebilirim?Renk çubuğu boyutu uyuşmazlığı örneği



@ imjohns3 Bu yazıdaki hiçbir şey renk çubuğuna hiçbir şey yapmıyor gibi görünüyor. Ne ayarlasam da aynı boyutta kalır. Kesir ve küçültürsem, renk çubuğu aynı kalırken grafiğin boyutu değişecek, zaten sahip olduğum şeye geri dönene kadar, hiçbir şey yapmayı bırakıyorlar.
Elliot

Matplotlib.org/api/colorbar_api.html dokümanlarına göz atın ve fractionveya shrinkargs kullanın .
BoltzmannBrain

Yanıtlar:


194

Bunu bir matplotlib AxisDivider ile kolayca yapabilirsiniz .

Bağlantılı sayfadaki örnek alt grafikler kullanmadan da çalışır:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

plt.figure()
ax = plt.gca()
im = ax.imshow(np.arange(100).reshape((10,10)))

# create an axes on the right side of ax. The width of cax will be 5%
# of ax and the padding between cax and ax will be fixed at 0.05 inch.
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)

plt.colorbar(im, cax=cax)

resim açıklamasını buraya girin


1
Bir alt alanın içinde çalışmıyorum, bu yüzden bu geçerli değil.
Elliot

Çok uğraştıktan sonra, işe yaradı. Subplot_adjust ile etkileşimde çok fazla sorun var, aramaları birbirine göre doğru yerlere almanız gerekiyor.
Elliot

11
Bu, grafiklerin boyutlarını biraz değiştiriyor. Ben bir 2x2 ızgara 4 var, ama sadece sağda çubuklar (ölçek satır uygulanır) sahip olmak istiyorum. Ancak bu onları aynı boyutta değil. Sadece renk çubuğu çağrısı (bölücü çağrısı ile) sahip değil denedim, ama tabii ki bu boş bir beyaz kutu ve yan numaraları bırakır. Hepsine çubuk koymadan tutarlı bir boyuta sahip olmalarını nasıl sağlayabilirim?
Elliot

@bogatron Ne yazık ki bu öngörülen eksenlerle çalışmaz
Bogdan

plt.titleDüğmesini kullanarak bir başlık eklemek isterseniz, başlık sağa takas olarak görüntülenir. Bunun üstesinden gelmenin bir yolu var mı?
user2820579

225

Bu kombinasyon (ve bunlara yakın değerler), ekranın boyutu ne olursa olsun, renk çubuğunu çizimde ölçeklendirmek için "sihirli bir şekilde" işe yarıyor gibi görünüyor.

plt.colorbar(im,fraction=0.046, pad=0.04)

Ayrıca, arsa kareden çıkarabilecek eksenin paylaşılmasını gerektirmez.


4
Bu bazı durumlarda işe yarayabilir, ancak genellikle işe yaramaz. Örneğin, orijinal sorudaki gibi, yüksekliğinin iki katı genişliğinde bir şey çizmeyi deneyin.
Matthias

Çizginin yüksekliğine uyacak şekilde ölçeklendirilmişse, kesir seçeneği yine de belirttiğiniz durumda işe yarıyor gibi görünüyor. (mpl
v1.4.3

6
Bunu yapmanın tek evrensel yolu budur. Axex_grid1 ile çözümler GeoAxes gibi yansıtılan eksenler için çalışmaz.
Bogdan

Aman tanrım bu harika. Çözüm için çok teşekkür ederim
2D_

3
@Matthias yorumuna yanıt olarak. Bu hileyi kullanarak görüntünün çok geniş olduğu durumu düzeltebilirsiniz: görüntünüz im_ratio = data.shape[0]/data.shape[1] plt.colorbar(im,fraction=0.046*im_ratio, pad=0.04)nerede data.
eindzl

30

@bogatron , doğru yüksekliği üreten matplotlib dokümanlarının önerdiği cevabı zaten verdi , ancak farklı bir sorun getiriyor. Şimdi renk çubuğunun genişliği (ve ayrıca renk çubuğu ve grafik arasındaki boşluk) grafiğin genişliği ile değişir. Başka bir deyişle, renk çubuğunun en boy oranı artık sabit değildir.

Doğru yüksekliği hem almak için ve belirli bir boy oranı, gizemli derinliklerine biraz kazmak zorunda axes_grid1modülü.

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable, axes_size
import numpy as np

aspect = 20
pad_fraction = 0.5

ax = plt.gca()
im = ax.imshow(np.arange(200).reshape((20, 10)))
divider = make_axes_locatable(ax)
width = axes_size.AxesY(ax, aspect=1./aspect)
pad = axes_size.Fraction(pad_fraction, width)
cax = divider.append_axes("right", size=width, pad=pad)
plt.colorbar(im, cax=cax)

Bunun çizimin yüksekliği için renk çubuğunun genişliğini belirlediğine dikkat edin ( şeklin genişliğinin aksine , eskisi gibi).

Renk çubuğu ve çizim arasındaki boşluk, artık renk çubuğunun genişliğinin bir kısmı olarak belirtilebilir, bu IMHO, şekil genişliğinin bir kısmından çok daha anlamlı bir sayıdır.

colorbar ile görüntü grafiği

GÜNCELLEME:

Ben yukarıdaki kodu kolayca yeniden kullanılabilir bir fonksiyon içine paketlenmiş konu üzerinde bir IPython defter oluşturdum :

import matplotlib.pyplot as plt
from mpl_toolkits import axes_grid1

def add_colorbar(im, aspect=20, pad_fraction=0.5, **kwargs):
    """Add a vertical color bar to an image plot."""
    divider = axes_grid1.make_axes_locatable(im.axes)
    width = axes_grid1.axes_size.AxesY(im.axes, aspect=1./aspect)
    pad = axes_grid1.axes_size.Fraction(pad_fraction, width)
    current_ax = plt.gca()
    cax = divider.append_axes("right", size=width, pad=pad)
    plt.sca(current_ax)
    return im.axes.figure.colorbar(im, cax=cax, **kwargs)

Bu şekilde kullanılabilir:

im = plt.imshow(np.arange(200).reshape((20, 10)))
add_colorbar(im)

1
Bu gerçekten yararlı küçük bir işlev! Bir uyarı kelimesi, birden fazla renk çubuğu eklemek istediğinizde çalışmaz, çünkü bunlar birbirinin üstünde görünür.
David Hall

22

Yukarıdaki tüm cevapları takdir ediyorum. Bazı cevaplar ve yorumlar işaret gibi Ancak, axes_grid1modül adres GeoAxes, ayarlama oysa edemez fraction, pad, shrinkve diğer benzer parametreler mutlaka beni gerçekten rahatsız çok hassas düzeni, veremez. colorbarKendi başına vermenin, axesbahsi geçen tüm konuları ele almak için daha iyi bir çözüm olabileceğine inanıyorum .

kod

import matplotlib.pyplot as plt
import numpy as np

fig=plt.figure()
ax = plt.axes()
im = ax.imshow(np.arange(100).reshape((10,10)))

# Create an axes for colorbar. The position of the axes is calculated based on the position of ax.
# You can change 0.01 to adjust the distance between the main image and the colorbar.
# You can change 0.02 to adjust the width of the colorbar.
# This practice is universal for both subplots and GeoAxes.

cax = fig.add_axes([ax.get_position().x1+0.01,ax.get_position().y0,0.02,ax.get_position().height])
plt.colorbar(im, cax=cax) # Similar to fig.colorbar(im, cax = cax)

Sonuç

resim açıklamasını buraya girin

Daha sonra, matplotlib.pyplot.colorbarresmi belgelerin de axrenk çubuğuna yer açacak mevcut eksenler olan seçenek sunduğunu görüyorum. Bu nedenle, birden fazla alt grafik için yararlıdır, aşağıdakilere bakın.

kod

fig, ax = plt.subplots(2,1,figsize=(12,8)) # Caution, figsize will also influence positions.
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
fig.colorbar(im1, ax=ax)

Sonuç

resim açıklamasını buraya girin

Yine, bakış açımdan daha doğru bir yol olan cax belirterek de benzer efektler elde edebilirsiniz.

kod

fig, ax = plt.subplots(2,1,figsize=(12,8))
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
cax = fig.add_axes([ax[1].get_position().x1-0.25,ax[1].get_position().y0,0.02,ax[0].get_position().y1-ax[1].get_position().y0])
fig.colorbar(im1, cax=cax)

Sonuç

resim açıklamasını buraya girin


@ HS-nebula Yorumlarınız için teşekkür ederiz, çok memnun oldum. :)
Fei Yao

Gerçekten şaşırtıcı bir cevap. Teşekkür ederim!!
episodeyang

11

Oluşturduğunuzda colorbarkesir ve / veya daraltma parametrelerini deneyin.

Belgelerden:

fraksiyon 0.15; colorbar için kullanılacak orijinal eksenlerin oranı

küçültmek 1.0; renk çubuğunu küçültecek kesir


1
Shrink 1.0 ve fraksiyonu herhangi bir şeye ayarlarsam, fraksiyonu değiştirmek tam olarak sahip olduğum şey haline gelene kadar, renk çubuğunun boyutunu etkilemeden grafiği küçültür, bu noktada onları değiştirmek bir şey yapmayı bırakır.
Elliot

Onları tam olarak belirttiğiniz yerde, colorbar()işleve veya yönteme ilişkin parametreler olması gerekir .
Steve Barnes

Teşekkürler. shrink parametresini belirtmeniz yeterlidir ve sihir gibi çalışır!
CodingNow

11

Yukarıdaki tüm çözümler iyi, ancak fantezi çağrıları içermediği ve evrensel oldukları için @ Steve'in ve @ bejota'nın en iyisini seviyorum.

Evrensel derken, bunun da dahil olmak üzere her türlü eksenle çalıştığını kastediyorum GeoAxes. Örneğin, eşleme için eksenleri yansıttınız:

projection = cartopy.crs.UTM(zone='17N')
ax = plt.axes(projection=projection)
im = ax.imshow(np.arange(200).reshape((20, 10)))

çağrı

cax = divider.append_axes("right", size=width, pad=pad)

ile başarısız olacak: KeyException: map_projection

Bu nedenle, tüm eksen türleri ile renk çubuğu boyutunu ele almanın tek evrensel yolu:

ax.colorbar(im, fraction=0.046, pad=0.04)

En iyi boyutunuzu elde etmek için 0,035'ten 0,046'ya kadar kesirle çalışın. Bununla birlikte, kesir ve paddig değerlerinin çiziminiz için en iyi uyumu sağlayacak şekilde ayarlanması gerekir ve renk çubuğunun yönü dikey konumda mı yoksa yatay mı olduğuna göre değişir.


1
Ayrıca ekleyebilir shrinkzaman parametresi fractionile birlikte padyeterince istenilen sonuçları yoktur.
Fei Yao
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.