Question

I possède une séquence de tracés linéaires pour deux variables (x, y) pour un certain nombre de différentes valeurs d'une variable z. Je normalement ajouter les tracés linéaires 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 de graphiques et les légendes couvrirai le graphique. Je préfère avoir un colorbar indiquant la valeur de z correspondant à la couleur. Je ne peux pas trouver quelque chose comme ça dans la galerie et toutes mes tentatives faire affaire avec le colorbar a échoué. Apparemment, je dois créer une collection de parcelles avant d'essayer d'ajouter un colorbar.

Y at-il un moyen facile de le faire? Merci.

EDIT (clarification):

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 fonctionnera pas selon la référence Matplotlib parce qu'une liste des parcelles ne sont pas un « cartographiables », quel que soit ce moyen.

J'ai créé une fonction de tracé alternatif 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 pour coloriser chaque ligne. Il se sent un peu comme un cludge bien ... Je pensais qu'il y aurait une façon plus propre de le faire. J'aime la flexibilité de la fonction plt.plot().

Était-ce utile?

La solution

(je sais que c'est une vieille question, mais ...) ont besoin d'un Colorbars matplotlib.cm.ScalarMappable, plt.plot produit des lignes qui ne sont pas mappable scalaire, donc, afin de faire un colorbar, nous allons devoir faire un mappable scalaire.

Ok. Ainsi, le constructeur d'une ScalarMappable prend cmap et une instance de norm. (Normes échelle des données à la gamme 0-1, Cmaps vous avez déjà travaillé avec et prendre un nombre compris entre 0-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 la création de sm à:

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

L'espoir qui 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)

EDIT : Pour matplotlib v1.3 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)

EDIT : Pour matplotlib v3.1 ou plus Simplifie à:

import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))
plt.colorbar(sm)

Autres conseils

Voici une façon de le faire tout en utilisant plt.plot (). Au fond, vous faites un terrain à jeter et obtenir le colorbar à 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()

Il est un peu inutile, mais pratique. Il est pas très inutile si vous faites plusieurs tracés que vous pouvez appeler plt.colorbar () sans régénération de l'information pour elle.

entrer image description ici

Voici un exemple légèrement simpliee inspiré par la réponse donnée par Boris et Hooked (Merci pour la grande idée!):

1. Discrète colorbar

Discret colorbar est plus impliqué, parce que colormap généré par mpl.cm.get_cmap() n'est pas une image mappable nécessaire comme argument colorbar(). A dummie mappable besoins de produit comme indiqué ci-dessous:

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

n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)

cmap = mpl.cm.get_cmap('jet', n_lines)

fig, ax = plt.subplots(dpi=100)
# Make dummie mappable
dummie_cax = ax.scatter(c, c, c=c, cmap=cmap)
# Clear axis
ax.cla()
for i, yi in enumerate(y.T):
    ax.plot(x, yi, c=cmap(i))
fig.colorbar(dummie_cax, ticks=c)
plt.show();

Cela produira une parcelle avec un colorbar discret: entrer la description d'image ici


2. colorbar continu

colorbar en continu est moins impliqué, comme mpl.cm.ScalarMappable() nous permet d'obtenir une « image » pour colorbar().

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


n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)

norm = mpl.colors.Normalize(vmin=c.min(), vmax=c.max())
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.jet)
cmap.set_array([])

fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
    ax.plot(x, yi, c=cmap.to_rgba(i + 1))
fig.colorbar(cmap, ticks=c)
plt.show();

Cela produira une parcelle avec une colorbar continue: entrer la description d'image ici

[note] Side Dans cet exemple, je ne sais pas pourquoi personnellement cmap.set_array([]) est nécessaire (sinon nous obtiendrions des messages d'erreur). Si quelqu'un comprend les principes sous le capot, s'il vous plaît commentaire:)

Comme d'autres réponses ici essaient d'utiliser des parcelles fictives, ce qui est pas vraiment un bon style, voici un code générique pour un

Discrète colorbar

On réalise un colorbar discret de la même façon est créée une colorbar continue, juste avec une autre normalisation. Dans ce cas, un BoundaryNorm doit être utilisé.

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

n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1., n_lines + 1)

cmap = plt.get_cmap("jet", len(c))
norm = matplotlib.colors.BoundaryNorm(np.arange(len(c)+1)+0.5,len(c))
sm = plt.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])  # this line may be ommitted for matplotlib >= 3.1

fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
    ax.plot(x, yi, c=cmap(i))
fig.colorbar(sm, ticks=c)
plt.show()

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top