web-dev-qa-db-fra.com

Définir la taille de la barre de couleur Matplotlib pour correspondre au graphique

Je ne peux pas obtenir que la barre de couleur sur les graphiques imshow tels que celui-ci ait la même hauteur que le graphique, à moins d'utiliser Photoshop après coup. Comment puis-je obtenir les hauteurs pour correspondre?Example of the colorbar size mismatch

124
Elliot

Vous pouvez le faire facilement avec un matplotlib AxisDivider .

L'exemple de la page liée fonctionne également sans sous-parcelles:

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)

enter image description here

157
bogatron

Cette combinaison (et les valeurs proches de celles-ci) semble "magiquement" me permettre de garder la barre de couleur à l'échelle du tracé, quelle que soit la taille de l'affichage.

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

Il n’exige pas non plus de partager l’axe, ce qui peut rendre l’intrigue déséquilibrée.

173
skytaker

@bogatron a déjà donné la réponse suggérée par le matplotlib docs , qui produit la bonne hauteur, mais pose un problème différent. Maintenant, la largeur de la barre de couleur (ainsi que l'espace entre la barre de couleur et le tracé) change avec la largeur du tracé. En d'autres termes, le rapport hauteur/largeur de la barre de couleur n'est plus fixe.

Pour obtenir à la fois la bonne hauteur et un rapport d'aspect donné, vous devez creuser un peu plus profondément dans le mystérieux module axes_grid1.

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)

Notez que ceci spécifie la largeur de la barre de couleurs w.r.t. la hauteur du tracé (par opposition à la largeur de la figure , comme c'était avant).

L'espacement entre la barre de couleur et le tracé peut maintenant être spécifié en tant que fraction de la largeur de la barre de couleur, ce qui représente à mon humble avis un nombre beaucoup plus significatif que celui d'une fraction de la largeur de la figure.

image plot with colorbar

MISE À JOUR:

J'ai créé n bloc-notes IPython sur le sujet , où j'ai condensé le code ci-dessus dans une fonction facilement réutilisable:

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)

Il peut être utilisé comme ceci:

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

Lorsque vous créez le colorbar essayez d'utiliser les paramètres de fraction et/ou de réduction.

Parmi les documents:

fraction 0,15; fraction d'axes d'origine à utiliser pour la barre de couleur

rétrécir 1,0; fraction par laquelle réduire la barre de couleur

8
Steve Barnes

Toutes les solutions ci-dessus sont bonnes, mais j'aime bien @ Steve's et @ bejota's car ils n'impliquent pas d'appels sophistiqués et sont universels.

Par universel, je veux dire qui fonctionne avec tout type d’axes, y compris GeoAxes. Par exemple, si vous avez projeté des axes pour la cartographie:

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

un appel à

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

échouera avec: KeyException: map_projection

Par conséquent, la seule façon universelle de traiter la taille de la barre de couleur avec tous les types d’axes est la suivante:

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

Travaillez avec des fractions de 0,035 à 0,046 pour obtenir la meilleure taille. Cependant, les valeurs de la fraction et de la valeur paddig devront être ajustées pour obtenir le meilleur ajustement possible pour votre tracé et différeront selon que l'orientation de la barre de couleur est en position verticale ou horizontale.

7
Bogdan

J'apprécie toutes les réponses ci-dessus. Cependant, comme certaines réponses et commentaires l'ont souligné, le module axes_grid1 ne peut pas traiter les fichiers GeoAxes, tandis que l'ajustement de fraction, pad, shrink et d'autres paramètres similaires ne peuvent pas nécessairement donner la ordre précis, ce qui me dérange vraiment. Je pense que donner à la colorbar sa propre axes pourrait être une meilleure solution pour résoudre tous les problèmes mentionnés.

Code

import matplotlib.pyplot as plt
import numpy as np

fig=plt.figure()
ax = plt.gca()
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)

Résultat

enter image description here

3
Fei Yao