Je trace plusieurs lignes sur un même tracé et je veux qu'elles couvrent tout le spectre d'une palette de couleurs, pas uniquement les mêmes 6 ou 7 couleurs. Le code s'apparente à ceci:
for i in range(20):
for k in range(100):
y[k] = i*x[i]
plt.plot(x,y)
plt.show()
Avec la palette de couleurs "jet" et une autre importée de Seaborn, les 7 mêmes couleurs sont répétées dans le même ordre. J'aimerais pouvoir tracer jusqu'à ~ 60 lignes différentes, toutes avec des couleurs différentes.
Les tables de couleurs Matplotlib acceptent un argument (0..1
, scalaire ou un tableau) que vous utilisez pour obtenir les couleurs d'une carte de couleurs. Par exemple:
col = pl.cm.jet([0.25,0.75])
Vous donne un tableau avec (deux) couleurs RGBA:
tableau ([[0., 0.50392157, 1., 1.], [1., 0.58169935, 0., 1.]])
Vous pouvez l'utiliser pour créer N
différentes couleurs:
import numpy as np
import matplotlib.pylab as pl
x = np.linspace(0, 2*np.pi, 64)
y = np.cos(x)
pl.figure()
pl.plot(x,y)
n = 20
colors = pl.cm.jet(np.linspace(0,1,n))
for i in range(n):
pl.plot(x, i*y, color=colors[i])
La solution de Bart est simple et agréable, mais présente deux inconvénients.
plt.colorbar()
ne fonctionnera pas de façon agréable, car les tracés linéaires ne sont pas mappables (par exemple, une image)
Cela peut être lent pour un grand nombre de lignes en raison de la boucle for (bien que cela ne pose peut-être pas un problème pour la plupart des applications?)
Ces problèmes peuvent être résolus en utilisant LineCollection
. Cependant, ce n'est pas trop convivial selon mon (humble) opinion. Il existe une suggestion ouverte sur GitHub pour l’ajout d’une fonction de tracé de tracé multicolore, similaire à la fonction plt.scatter(...)
.
Voici un exemple de travail que j'ai pu pirater
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
def multiline(xs, ys, c, ax=None, **kwargs):
"""Plot lines with different colorings
Parameters
----------
xs : iterable container of x coordinates
ys : iterable container of y coordinates
c : iterable container of numbers mapped to colormap
ax (optional): Axes to plot on.
kwargs (optional): passed to LineCollection
Notes:
len(xs) == len(ys) == len(c) is the number of line segments
len(xs[i]) == len(ys[i]) is the number of points for each line (indexed by i)
Returns
-------
lc : LineCollection instance.
"""
# find axes
ax = plt.gca() if ax is None else ax
# create LineCollection
segments = [np.column_stack([x, y]) for x, y in Zip(xs, ys)]
lc = LineCollection(segments, **kwargs)
# set coloring of line segments
# Note: I get an error if I pass c as a list here... not sure why.
lc.set_array(np.asarray(c))
# add lines to axes and rescale
# Note: adding a collection doesn't autoscalee xlim/ylim
ax.add_collection(lc)
ax.autoscale()
return lc
Voici un exemple très simple:
xs = [[0, 1],
[0, 1, 2]]
ys = [[0, 0],
[1, 2, 1]]
c = [0, 1]
lc = multiline(xs, ys, c, cmap='bwr', lw=2)
Produit:
Et quelque chose d'un peu plus sophistiqué:
n_lines = 30
x = np.arange(100)
yint = np.arange(0, n_lines*10, 10)
ys = np.array([x + b for b in yint])
xs = np.array([x for i in range(n_lines)]) # could also use np.tile
colors = np.arange(n_lines)
fig, ax = plt.subplots()
lc = multiline(xs, ys, yint, cmap='bwr', lw=2)
axcb = fig.colorbar(lc)
axcb.set_label('Y-intercept')
ax.set_title('Line Collection with mapped colors')
Produit:
J'espère que cela t'aides!
Une alternative à la réponse de Bart, dans laquelle vous ne spécifiez pas la couleur dans chaque appel à plt.plot
, consiste à définir un nouveau cycle de couleur avec set_prop_cycle
. Son exemple peut être traduit dans le code suivant (j'ai également modifié l'importation de matplotlib dans le style recommandé):
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 64)
y = np.cos(x)
n = 20
ax = plt.axes()
ax.set_prop_cycle('color',[plt.cm.jet(i) for i in np.linspace(0, 1, n)])
for i in range(n):
plt.plot(x, i*y)
Si vous utilisez des palettes de couleurs continues comme brg, hsv, jet ou celle par défaut, vous pouvez procéder comme suit:
color = plt.cm.hsv(r) # r is 0 to 1 inclusive
Maintenant, vous pouvez transmettre cette valeur de couleur à n’importe quelle API de ce type:
line = matplotlib.lines.Line2D(xdata, ydata, color=color)