69 votes

Matplotlib - ajoute une barre de couleur à une séquence de tracés linéaires

J'ai une séquence de ligne de parcelles pour les deux variables (x,y) pour un certain nombre de valeurs d'une variable z. Normalement j'ajoutez la ligne des parcelles avec des légendes comme ceci:

import matplotlib.pyplot as plt

fig = plt.figure()
ax  = fig.add_subplot(111)
# suppose mydata is a list of tuples containing (xs, ys, z) 
# where xs and ys are lists of x's and y's and z is a number. 
legns = []
for(xs,ys,z) in mydata:
   pl = ax.plot(xs,ys,color = (z,0,0))
   legns.append("z = %f"%(z))
ax.legends(legns) 
plt.show()

Mais j'ai trop nombreux graphiques et les légendes couvrira le graphique. Je préfère avoir une barre de couleur indiquant la valeur de z correspondant à la couleur. Je ne peux pas trouver quelque chose comme ça dans la galerie, et toutes mes tentatives de faire face avec la barre de couleur échoué. Apparemment, je dois créer une collection de parcelles avant d'essayer d'ajouter une barre de couleur.

Est-il un moyen facile de faire cela? Merci.

EDIT (précisions):

Je voulais faire quelque chose comme ceci:

import matplotlib.pyplot as plt
import matplotlib.cm     as cm

fig = plt.figure()
ax  = fig.add_subplot(111)
mycmap = cm.hot
# suppose mydata is a list of tuples containing (xs, ys, z) 
# where xs and ys are lists of x's and y's and z is a number between 0 and 1
plots = []
for(xs,ys,z) in mydata:
   pl = ax.plot(xs,ys,color = mycmap(z))
   plots.append(pl)
fig.colorbar(plots)
plt.show()

Mais cela ne fonctionne pas selon le Matplotlib référence parce que une liste de parcelles n'est pas un "assignable", quoi que cela signifie.

J'ai créé un autre parcelle de la fonction en utilisant LineCollection:

def myplot(ax,xs,ys,zs, cmap):
    plot = lc([zip(x,y) for (x,y) in zip(xs,ys)], cmap = cmap)
    plot.set_array(array(zs))
    x0,x1 = amin(xs),amax(xs)
    y0,y1 = amin(ys),amax(ys)
    ax.add_collection(plot)
    ax.set_xlim(x0,x1)
    ax.set_ylim(y0,y1)
    return plot

xs et ys sont des listes de listes de coordonnées x et y et zs est une liste des différentes conditions à colorer chaque ligne. Il se sent un peu comme un cludge bien... je pensais qu'il y aurait une plus belle façon de le faire. J'aime la souplesse de l' plt.plot() fonction.

121voto

pelson Points 5011

(Je sais c'est une vieille question, mais...) Colorbars besoin d'un matplotlib.cm.ScalarMappable, plt.plot produit des lignes qui ne sont pas scalaire transposable, par conséquent, afin de faire une barre de couleur, nous allons avoir besoin de faire un scalaire cartographiables.

Ok. Ainsi, le constructeur de l' ScalarMappable prend un cmap et norm de l'instance. (les normes de données à l'échelle de la gamme 0-1, cmaps vous avez déjà travaillé avec et prendre un nombre entre 0 et 1 et retourne une couleur). Donc dans votre cas:

import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(min=0, max=1))
plt.colorbar(sm)

Parce que vos données sont dans la gamme 0-1 déjà, vous pouvez simplifier l' sm création de:

sm = plt.cm.ScalarMappable(cmap=my_cmap)

Espérons que l'aide à quelqu'un.

EDIT: Pour matplotlib v1.2 ou plus, le code devient:

import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(vmin=0, vmax=1))
# fake up the array of the scalar mappable. Urgh...
sm._A = []
plt.colorbar(sm)

34voto

Boris Points 169

Voici une façon de le faire tout en utilisant plt.plot (). En gros, vous faites un tracé jetable et vous obtenez la barre de couleur à partir de là.

 import matplotlib as mpl
import matplotlib.pyplot as plt

min, max = (-40, 30)
step = 10

# Setting up a colormap that's a simple transtion
mymap = mpl.colors.LinearSegmentedColormap.from_list('mycolors',['blue','red'])

# Using contourf to provide my colorbar info, then clearing the figure
Z = [[0,0],[0,0]]
levels = range(min,max+step,step)
CS3 = plt.contourf(Z, levels, cmap=mymap)
plt.clf()

# Plotting what I actually want
X=[[1,2],[1,2],[1,2],[1,2]]
Y=[[1,2],[1,3],[1,4],[1,5]]
Z=[-40,-20,0,30]
for x,y,z in zip(X,Y,Z):
    # setting rgb color based on z normalized to my range
    r = (float(z)-min)/(max-min)
    g = 0
    b = 1-r
    plt.plot(x,y,color=(r,g,b))
plt.colorbar(CS3) # using the colorbar info I got from contourf
plt.show()
 

C'est un peu inutile, mais pratique. Ce n'est pas non plus une perte de temps si vous créez plusieurs parcelles, car vous pouvez appeler plt.colorbar () sans régénérer les informations correspondantes.

entrez la description de l'image 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