Comment obtenir différentes lignes colorées pour différentes parcelles en une seule figure?

202

J'utilise matplotlibpour créer les parcelles. Je dois identifier chaque intrigue avec une couleur différente qui devrait être générée automatiquement par Python.

Pouvez-vous s'il vous plaît me donner une méthode pour mettre différentes couleurs pour différentes parcelles dans la même figure?

pottigopi
la source

Réponses:

424

Matplotlib fait cela par défaut.

Par exemple:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)
plt.show()

Diagramme de base démontrant le cycle des couleurs

Et, comme vous le savez peut-être déjà, vous pouvez facilement ajouter une légende:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Intrigue de base avec légende

Si vous souhaitez contrôler les couleurs à parcourir:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.gca().set_color_cycle(['red', 'green', 'blue', 'yellow'])

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Graphique montrant le contrôle du cycle de couleur par défaut

Si vous n'êtes pas familier avec matplotlib, le tutoriel est un bon point de départ .

Éditer:

Tout d'abord, si vous avez beaucoup (> 5) de choses que vous souhaitez tracer sur une figure, soit:

  1. Mettez-les sur différentes parcelles (pensez à utiliser quelques sous-parcelles sur une figure), ou
  2. Utilisez autre chose que la couleur (c.-à-d. Les styles de marqueur ou l'épaisseur de ligne) pour les distinguer.

Sinon, vous allez vous retrouver avec un complot très salissant! Soyez gentil avec qui jamais lira ce que vous faites et n'essayez pas de mettre 15 choses différentes sur une seule figure !!

Au-delà de cela, de nombreuses personnes sont daltoniennes à des degrés divers, et la distinction entre de nombreuses couleurs subtilement différentes est difficile pour plus de gens que vous ne le pensez.

Cela dit, si vous voulez vraiment mettre 20 lignes sur un axe avec 20 couleurs relativement distinctes, voici une façon de le faire:

import matplotlib.pyplot as plt
import numpy as np

num_plots = 20

# Have a look at the colormaps here and decide which one you'd like:
# http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html
colormap = plt.cm.gist_ncar
plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))

# Plot several different functions...
x = np.arange(10)
labels = []
for i in range(1, num_plots + 1):
    plt.plot(x, i * x + 5 * i)
    labels.append(r'$y = %ix + %i$' % (i, 5*i))

# I'm basically just demonstrating several different legend options here...
plt.legend(labels, ncol=4, loc='upper center', 
           bbox_to_anchor=[0.5, 1.1], 
           columnspacing=1.0, labelspacing=0.0,
           handletextpad=0.0, handlelength=1.5,
           fancybox=True, shadow=True)

plt.show()

Couleurs uniques pour 20 lignes basées sur une palette de couleurs donnée

Joe Kington
la source
17
Remarque pour le dernier exemple, dans les versions plus récentes de matplotlib, le set_color_cyclea été déconseillé, de sorte que cette ligne devrait être plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))et juste changer le plt.cm.YOUR_PREFERED_COLOR_MAPpour l'adapter à vos besoins.
Nate
1
@JoeKington: L'explication était merveilleuse, merci beaucoup
Rika
c'est bien. existe-t-il un moyen de les rendre interactifs? par exemple, dans RI, convertir ggplot en ggplotly (), et le graphique devient html interactif
kRazzy R
Je suis convaincu que l'OP savait que Matplotlib colore de manière appropriée différentes courbes dans une seule parcelle (dans une seule axes) et a demandé comment faire varier la couleur d'une seule ligne dans différentes parcelles (différentes axes) ... Cela dit, excellente réponse à une importante question (peut-être différente de ce que OP a demandé, mais personne ne peut le dire car ils ont posé cette seule question et ont disparu!) - +1
gboffi
37

Les définir plus tard

Si vous ne connaissez pas le nombre de tracés que vous allez tracer, vous pouvez changer les couleurs une fois que vous les avez tracées en récupérant le nombre directement à partir du tracé en utilisant .lines, j'utilise cette solution:

Quelques données aléatoires

import matplotlib.pyplot as plt
import numpy as np

fig1 = plt.figure()
ax1 = fig1.add_subplot(111)


for i in range(1,15):
    ax1.plot(np.array([1,5])*i,label=i)

Le morceau de code dont vous avez besoin:

colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired   
colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))]
for i,j in enumerate(ax1.lines):
    j.set_color(colors[i])
  

ax1.legend(loc=2)

Le résultat est le suivant:entrez la description de l'image ici

GM
la source
8

TL; DR Non, cela ne peut pas être fait automatiquement . Oui c'est possible.

import matplotlib.pyplot as plt
my_colors = plt.rcParams['axes.prop_cycle']() # <<< note that we CALL the prop_cycle
fig, axes = plt.subplots(2,3)
for ax in axes.flatten(): ax.plot((0,1), (0,1), **next(my_colors))

entrez la description de l'image ici Chaque tracé ( axes) dans une figure ( figure) a son propre cycle de couleurs - si vous ne forcez pas une couleur différente pour chaque tracé, tous les tracés partagent le même ordre de couleurs mais, si nous étirons un peu ce que signifie "automatiquement" , ça peut être fait.


L'OP a écrit

[...] Je dois identifier chaque tracé avec une couleur différente qui devrait être générée automatiquement par [Matplotlib].

Mais ... Matplotlib génère automatiquement des couleurs différentes pour chaque courbe différente

In [10]: import numpy as np
    ...: import matplotlib.pyplot as plt

In [11]: plt.plot((0,1), (0,1), (1,2), (1,0));
Out[11]:

entrez la description de l'image ici

Alors pourquoi la demande OP? Si nous continuons à lire, nous avons

Pouvez-vous s'il vous plaît me donner une méthode pour mettre différentes couleurs pour différentes parcelles dans la même figure?

et cela a du sens, car chaque intrigue (chacune axesdans le langage de Matplotlib) a sa propre color_cycle(ou plutôt, en 2018, son prop_cycle) et chaque intrigue ( axes) réutilise les mêmes couleurs dans le même ordre.

In [12]: fig, axes = plt.subplots(2,3)

In [13]: for ax in axes.flatten():
    ...:     ax.plot((0,1), (0,1))

entrez la description de l'image ici

Si tel est le sens de la question d'origine, une possibilité consiste à nommer explicitement une couleur différente pour chaque tracé.

Si les tracés (comme cela arrive souvent) sont générés dans une boucle, nous devons avoir une variable de boucle supplémentaire pour remplacer la couleur choisie automatiquement par Matplotlib.

In [14]: fig, axes = plt.subplots(2,3)

In [15]: for ax, short_color_name in zip(axes.flatten(), 'brgkyc'):
    ...:     ax.plot((0,1), (0,1), short_color_name)

entrez la description de l'image ici

Une autre possibilité consiste à instancier un objet cycler

from cycler import cycler
my_cycler = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.])
actual_cycler = my_cycler()

fig, axes = plt.subplots(2,3)
for ax in axes.flat:
    ax.plot((0,1), (0,1), **next(actual_cycler))

entrez la description de l'image ici

Notez que type(my_cycler)c'est cycler.Cyclermais type(actual_cycler)est itertools.cycle.

gboffi
la source
3

Je voudrais offrir une amélioration mineure par rapport à la dernière réponse de boucle donnée dans le post précédent (ce post est correct et devrait encore être accepté). L'hypothèse implicite faite lors de l'étiquetage du dernier exemple est que le plt.label(LIST)numéro d'étiquette X LISTavec la ligne correspondant à la Xème fois a plotété appelé. J'ai déjà rencontré des problèmes avec cette approche. La façon recommandée de créer des légendes et de personnaliser leurs étiquettes selon la documentation de matplotlibs ( http://matplotlib.org/users/legend_guide.html#adjusting-the-order-of-legend-item ) est d'avoir un sentiment chaleureux que les étiquettes vont ainsi que les tracés exacts que vous pensez qu'ils font:

...
# Plot several different functions...
labels = []
plotHandles = []
for i in range(1, num_plots + 1):
    x, = plt.plot(some x vector, some y vector) #need the ',' per ** below
    plotHandles.append(x)
    labels.append(some label)
plt.legend(plotHandles, labels, 'upper left',ncol=1)

**: Matplotlib Legends ne fonctionne pas

Tommy
la source
3
Juste pour info: vous pouvez également utiliser le kwarg "label" pour tracer puis appeler légende sans aucun argument.
Joe Kington