185 votes

Définir la gamme de barres de couleur dans matplotlib

J'ai le code suivant :

import matplotlib.pyplot as plt

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

plt.clf()
plt.pcolor(X, Y, v, cmap=cm)
plt.loglog()
plt.xlabel('X Axis')
plt.ylabel('Y Axis')

plt.colorbar()
plt.show()

Cela produit un graphique des valeurs 'v' sur les axes X et Y, en utilisant la carte de couleurs spécifiée. Les axes X et Y sont parfaits, mais la carte de couleurs s'étend entre le minimum et le maximum de v. Je voudrais forcer la carte de couleurs à se situer entre 0 et 1.

J'ai pensé à utiliser :

plt.axis(...)

Pour définir les plages des axes, mais cela ne prend des arguments que pour le min et le max de X et Y, pas pour la carte des couleurs.

Edit :

Pour plus de clarté, disons que j'ai un graphique dont les valeurs sont comprises entre (0 ... 0,3), et un autre graphique dont les valeurs sont (0,2 ... 0,8).

Dans les deux graphiques, je souhaite que la gamme de la barre de couleur soit (0 ... 1). Dans les deux graphiques, je veux que cette gamme de couleur soit identique en utilisant la gamme complète de cdict ci-dessus (donc 0,25 dans les deux graphiques sera de la même couleur). Dans le premier graphique, toutes les couleurs comprises entre 0,3 et 1,0 ne figureront pas dans le graphique, mais dans la barre de couleurs située sur le côté. Dans l'autre, toutes les couleurs comprises entre 0 et 0,2, et entre 0,8 et 1 n'apparaîtront pas dans le graphique, mais dans la barre de couleurs sur le côté.

208voto

tom10 Points 19886

Utilisation de vmin et vmax force la gamme pour les couleurs. Voici un exemple :

enter image description here

import matplotlib as m
import matplotlib.pyplot as plt
import numpy as np

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

x = np.arange(0, 10, .1)
y = np.arange(0, 10, .1)
X, Y = np.meshgrid(x,y)

data = 2*( np.sin(X) + np.sin(3*Y) )

def do_plot(n, f, title):
    #plt.clf()
    plt.subplot(1, 3, n)
    plt.pcolor(X, Y, f(data), cmap=cm, vmin=-4, vmax=4)
    plt.title(title)
    plt.colorbar()

plt.figure()
do_plot(1, lambda x:x, "all")
do_plot(2, lambda x:np.clip(x, -4, 0), "<0")
do_plot(3, lambda x:np.clip(x, 0, 4), ">0")
plt.show()

4 votes

Pourquoi cette réponse est-elle meilleure que celle utilisant plt.clim postée par @Amro ?

108voto

Amro Points 72743

Utilisez le CLIM (équivalent à CAXIS dans MATLAB) :

plt.pcolor(X, Y, v, cmap=cm)
plt.clim(-4,4)  # identical to caxis([-4,4]) in MATLAB
plt.show()

4 votes

Je crois que clim() met à l'échelle les axes de couleur, mais les couleurs elles-mêmes changent de valeur. Le point situé à une certaine fraction de l'échelle aura la même couleur quelle que soit l'échelle, mais la valeur qu'il représente changera.

4 votes

Oui. C'est le comportement souhaité par le demandeur, ce qui résout le problème : que l'échelle de couleurs soit identique entre les graphiques.

19voto

nikow Points 8887

Je ne suis pas sûr que ce soit la solution la plus élégante (c'est ce que j'ai utilisé), mais vous pourriez mettre vos données à l'échelle de 0 à 1, puis modifier la barre de couleur :

import matplotlib as mpl
...
ax, _ = mpl.colorbar.make_axes(plt.gca(), shrink=0.5)
cbar = mpl.colorbar.ColorbarBase(ax, cmap=cm,
                       norm=mpl.colors.Normalize(vmin=-0.5, vmax=1.5))
cbar.set_clim(-2.0, 2.0)

Les deux limites différentes vous permettent de contrôler la portée et la légende de la barre de couleur. Dans cet exemple, seule la plage comprise entre -0,5 et 1,5 est affichée dans la barre, alors que la carte des couleurs couvre -2 à 2 (il pourrait donc s'agir de votre plage de données, que vous enregistrez avant la mise à l'échelle).

Ainsi, au lieu de mettre à l'échelle la carte des couleurs, vous mettez vos données à l'échelle et vous adaptez la barre de couleurs à cette échelle.

1 votes

Je pense que cela fait quelque chose de subtilement différent... désolé, je n'ai probablement pas été assez précis dans ma question. Votre solution mettra les couleurs à l'échelle de sorte que ce qui représentait la valeur 1,0 représentera désormais la valeur maximale dans mes données. La barre de couleur affichera 0..1 comme je le souhaite (avec vmin=0, vmax=1), mais tout ce qui est au-dessus de cette valeur maximale sera de la même couleur...

2 votes

... J'ai mis à jour ma question pour montrer plus clairement ce que je cherche. Désolé si j'étais trop vague.

16voto

G M Points 508

Utilisation de l'environnement des figures et de .set_clim()

Cette alternative pourrait être plus facile et plus sûre si vous avez plusieurs parcelles :

import matplotlib as m
import matplotlib.pyplot as plt
import numpy as np

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

x = np.arange(0, 10, .1)
y = np.arange(0, 10, .1)
X, Y = np.meshgrid(x,y)

data = 2*( np.sin(X) + np.sin(3*Y) )
data1 = np.clip(data,0,6)
data2 = np.clip(data,-6,0)
vmin = np.min(np.array([data,data1,data2]))
vmax = np.max(np.array([data,data1,data2]))

fig = plt.figure()
ax = fig.add_subplot(131)
mesh = ax.pcolormesh(data, cmap = cm)
mesh.set_clim(vmin,vmax)
ax1 = fig.add_subplot(132)
mesh1 = ax1.pcolormesh(data1, cmap = cm)
mesh1.set_clim(vmin,vmax)
ax2 = fig.add_subplot(133)
mesh2 = ax2.pcolormesh(data2, cmap = cm)
mesh2.set_clim(vmin,vmax)
# Visualizing colorbar part -start
fig.colorbar(mesh,ax=ax)
fig.colorbar(mesh1,ax=ax1)
fig.colorbar(mesh2,ax=ax2)
fig.tight_layout()
# Visualizing colorbar part -end

plt.show()

enter image description here

Une seule barre de couleur

La meilleure alternative est alors d'utiliser une seule barre de couleur pour l'ensemble de la parcelle. Il existe différentes façons de procéder, ce Le tutoriel est très utile pour comprendre la meilleure option. Je préfère cette solution que vous pouvez simplement copier et coller au lieu de la précédente visualisation de la partie colorée de la barre du code.

fig.subplots_adjust(bottom=0.1, top=0.9, left=0.1, right=0.8,
                    wspace=0.4, hspace=0.1)
cb_ax = fig.add_axes([0.83, 0.1, 0.02, 0.8])
cbar = fig.colorbar(mesh, cax=cb_ax)

enter image description here

P.S.

Je suggère d'utiliser pcolormesh au lieu de pcolor parce qu'il est plus rapide (plus infos ici ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X