J'ai passé trop de temps à rechercher comment obtenir deux sous-tracés pour partager le même axe y avec une seule barre de couleur partagée entre les deux dans Matplotlib.
Ce qui se passait, c'est que lorsque j'appelais la colorbar()
fonction dans l'un subplot1
ou l' autre subplot2
, elle mettait automatiquement l'échelle à l'échelle de sorte que la barre de couleurs plus l'intrigue s'adaptent à l'intérieur du cadre de délimitation du sous-intrigue, ce qui faisait que les deux tracés côte à côte étaient deux très différents tailles.
Pour contourner cela, j'ai essayé de créer une troisième sous-intrigue que j'ai ensuite piratée pour ne rendre aucune intrigue avec juste une barre de couleur présente. Le seul problème est que maintenant les hauteurs et les largeurs des deux parcelles sont inégales, et je ne peux pas comprendre comment le rendre correct.
Voici mon code:
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()
la source
vmin
etvmax
sont essentiels. Ils contrôlent la gamme de couleurs de chaque sous-intrigue. Si vous disposez de données réelles, vous devrez peut-être effectuer une analyse pour trouver les valeurs min et max en premier.Vous pouvez simplifier le code de Joe Kington en utilisant le
ax
paramètre defigure.colorbar()
avec une liste d'axes. De la documentation :la source
fig.colorbar(im, ax=axes.ravel().tolist())
. Si vous omettezax=axes.ravel().tolist()
, la barre de couleurs sera placée dans un sous-tracé.Cette solution ne nécessite pas de réglage manuel de l'emplacement des axes ou de la taille de la barre de couleur, fonctionne avec des dispositions à plusieurs lignes et à une seule ligne, et fonctionne avec
tight_layout()
. Il est adapté d'un exemple de galerie , en utilisantImageGrid
la boîte à outils AxesGrid de matplotlib .la source
thecb = ax.cax.colorbar(im)
. Ensuite, vous pouvez le fairethecb.set_label_text("foo")
L'utilisation
make_axes
est encore plus facile et donne un meilleur résultat. Il offre également des possibilités de personnaliser le positionnement de la barre de couleurs. Notez également l'option desubplots
partager les axes x et y.la source
nrows=1
, la barre de couleur redevient plus grande que les sous-tracés.En tant que débutant qui est tombé sur ce fil, je voudrais ajouter une adaptation python pour les nuls de la réponse très soignée d' abevieiramota (parce que je suis au niveau que j'ai dû rechercher `` ravel '' pour déterminer ce que leur code faisait):
Beaucoup moins pythonique, beaucoup plus facile pour les noobs comme moi de voir ce qui se passe réellement ici.
la source
Comme indiqué dans d'autres réponses, l'idée est généralement de définir des axes pour la barre de couleurs à résider. Il existe différentes façons de le faire; celui qui n'a pas encore été mentionné serait de spécifier directement les axes de la barre de couleur lors de la création du sous-tracé avec
plt.subplots()
. L'avantage est que la position des axes n'a pas besoin d'être réglée manuellement et dans tous les cas avec un aspect automatique, la barre de couleur aura exactement la même hauteur que les sous-tracés. Même dans de nombreux cas où des images sont utilisées, le résultat sera satisfaisant comme indiqué ci-dessous.Lors de l'utilisation
plt.subplots()
, l'utilisation d'gridspec_kw
argument permet de rendre les axes de la barre de couleur beaucoup plus petits que les autres axes.Exemple:
Cela fonctionne bien si l'aspect des tracés est mis à l'échelle automatiquement ou si les images sont rétrécies en raison de leur aspect dans le sens de la largeur (comme ci-dessus). Si, cependant, les images sont plus larges que hautes, le résultat se présenterait comme suit, ce qui pourrait être indésirable.
Une solution pour corriger la hauteur de colorbar à la hauteur de la sous - parcelle consisterait à utiliser
mpl_toolkits.axes_grid1.inset_locator.InsetPosition
pour définir les axes de colorbar par rapport aux axes de subplot d'image.la source
ax = fig.add_subplot()
place? Je demande parce que je ne sais pas comment l'utiliser avec le fond de carte.GridSpec
àadd_subplot()
dans ce cas.La solution d'utiliser une liste d'axes par abevieiramota fonctionne très bien jusqu'à ce que vous n'utilisiez qu'une seule ligne d'images, comme indiqué dans les commentaires. L'utilisation d'un rapport d'aspect raisonnable pour les
figsize
aides, mais est encore loin d'être parfaite. Par exemple:La fonction de barre de couleur fournit le
shrink
paramètre qui est un facteur d'échelle pour la taille des axes de la barre de couleur. Cela nécessite des essais et des erreurs manuels. Par exemple:la source
Pour ajouter à l'excellente réponse de @ abevieiramota, vous pouvez obtenir l'euqivalent de tight_layout avec constrained_layout. Vous obtiendrez toujours de grands espaces horizontaux si vous les utilisez
imshow
plutôtpcolormesh
qu'en raison du rapport d'aspect 1: 1 imposé parimshow
.la source
J'ai remarqué que presque toutes les solutions publiées impliquaient
ax.imshow(im, ...)
et ne normalisaient pas les couleurs affichées dans la barre de couleurs pour les sous-figures multiples. Leim
mappable provient de la dernière instance, mais que se passe-t-il si les valeurs des multiplesim
-s sont différentes? (Je suppose que ces mappables sont traités de la même manière que les ensembles de contours et les ensembles de surfaces.) J'ai un exemple utilisant un tracé de surface 3D ci-dessous qui crée deux barres de couleur pour un sous-tracé 2x2 (une barre de couleur par ligne) ). Bien que la question demande explicitement un arrangement différent, je pense que l'exemple aide à clarifier certaines choses. Je n'ai pas encore trouvé de moyen de le faire enplt.subplots(...)
raison des axes 3D malheureusement.Si seulement je pouvais mieux positionner les barres de couleurs ... (Il y a probablement une bien meilleure façon de le faire, mais au moins cela ne devrait pas être trop difficile à suivre.)
la source
im
sont différentes, elles ne devraient pas utiliser la même barre de couleurs, donc la question d'origine ne s'appliquerait pas vraimentCe sujet est bien couvert mais je voudrais quand même proposer une autre approche dans une philosophie légèrement différente.
Il est un peu plus complexe à mettre en place mais il permet (à mon avis) un peu plus de flexibilité. Par exemple, on peut jouer avec les ratios respectifs de chaque sous-parcelles / barre de couleurs:
la source