Come ottenere diverse linee colorate per diversi grafici in una singola figura?


202

Sto usando matplotlibper creare le trame. Devo identificare ogni trama con un colore diverso che dovrebbe essere generato automaticamente da Python.

Potete per favore darmi un metodo per mettere colori diversi per trame diverse nella stessa figura?

Risposte:


424

Matplotlib lo fa per impostazione predefinita.

Per esempio:

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()

Trama di base che dimostra il ciclismo dei colori

E, come forse già saprai, puoi facilmente aggiungere una legenda:

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()

Trama di base con legenda

Se vuoi controllare i colori che verranno ciclicati:

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()

Traccia che mostra il controllo sul ciclo di colori predefinito

Se non hai familiarità con matplotlib, il tutorial è un buon punto di partenza .

Modificare:

Prima di tutto, se hai molte (> 5) cose che vuoi tracciare su una figura, o:

  1. Inseriscili su diversi grafici (considera l'utilizzo di alcuni grafici secondari su una figura), oppure
  2. Usa qualcosa di diverso dal colore (ad es. Stili di pennarello o spessore della linea) per distinguerli.

Altrimenti, finirai con una trama molto disordinata! Sii gentile con chi leggerà qualunque cosa tu stia facendo e non provare a stipare 15 cose diverse su una figura !!

Oltre a ciò, molte persone sono daltoniche a vari livelli e distinguere tra numerosi colori leggermente diversi è difficile per più persone di quanto tu possa immaginare.

Detto questo, se vuoi davvero mettere 20 linee su un asse con 20 colori relativamente distinti, ecco un modo per farlo:

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()

Colori unici per 20 linee basati su una determinata mappa colori


17
Nota per l'ultimo esempio, nelle versioni più recenti di matplotlib, set_color_cycleè stato deprecato, quindi quella linea dovrebbe essere plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))e basta cambiare la plt.cm.YOUR_PREFERED_COLOR_MAPper adattarla alle tue esigenze.
Nate,

1
@JoeKington: la spiegazione è stata meravigliosa, grazie mille
Rika,

è fantastico c'è un modo per renderli interattivi? ad esempio in RI converti ggplot in ggplotly () e la trama diventa html interattiva
kRazzy R

Sono convinto che l'OP sapesse che Matplotlib colora opportunamente diverse curve in un singolo grafico (in un singolo axes) e ha chiesto di variare il colore di una singola linea in diversi grafici (diversi axes) ... Detto questo, un'ottima risposta a un importante domanda (forse diversa da quella che OP ha fatto, ma nessuno può dirlo perché hanno fatto questa singola domanda e sono scomparsi!) - +1
gboffi

37

Impostandoli più tardi

Se non si conosce il numero di grafici che si intende tracciare, è possibile modificare i colori dopo averli stampati recuperando il numero direttamente dal diagramma utilizzando .lines, utilizzo questa soluzione:

Alcuni dati casuali

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)

Il pezzo di codice che ti serve:

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)

Il risultato è il seguente:inserisci qui la descrizione dell'immagine


8

TL; DR No, non può essere fatto automaticamente . Sì, è possibile.

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))

inserisci qui la descrizione dell'immagine Ogni grafico ( axes) in una figura ( figure) ha il suo ciclo di colori - se non imponi un colore diverso per ogni grafico, tutti i grafici condividono lo stesso ordine di colori ma, se allunghiamo un po 'ciò che significa "automaticamente" , si può fare.


L'OP ha scritto

[...] Devo identificare ogni trama con un colore diverso che dovrebbe essere generato automaticamente da [Matplotlib].

Ma ... Matplotlib genera automaticamente colori diversi per ogni curva diversa

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]:

inserisci qui la descrizione dell'immagine

Quindi perché la richiesta OP? Se continuiamo a leggere, abbiamo

Potete per favore darmi un metodo per mettere colori diversi per trame diverse nella stessa figura?

e ha senso, perché ogni trama (ognuna axesnel linguaggio di Matplotlib) ha la sua color_cycle(o meglio, nel 2018, la sua prop_cycle) e ogni trama ( axes) riutilizza gli stessi colori nello stesso ordine.

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

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

inserisci qui la descrizione dell'immagine

Se questo è il significato della domanda originale, una possibilità è quella di nominare esplicitamente un colore diverso per ogni trama.

Se i grafici (come spesso accade) vengono generati in un ciclo, è necessario disporre di una variabile di ciclo aggiuntiva per sovrascrivere il colore scelto automaticamente da 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)

inserisci qui la descrizione dell'immagine

Un'altra possibilità è quella di istanziare un oggetto 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))

inserisci qui la descrizione dell'immagine

Nota che type(my_cycler)è cycler.Cyclerma type(actual_cycler)è itertools.cycle.


3

Vorrei offrire un piccolo miglioramento sull'ultima risposta del ciclo fornita nel post precedente (quel post è corretto e dovrebbe essere comunque accettato). Il presupposto implicito fatto quando si etichetta l'ultimo esempio è che plt.label(LIST)inserisce il numero di etichetta X LISTcon la linea corrispondente alla Xa volta plot. Ho incontrato problemi con questo approccio prima. Il modo raccomandato per costruire leggende e personalizzare le loro etichette in base alla documentazione di matplotlibs ( http://matplotlib.org/users/legend_guide.html#adjusting-the-order-of-legend-item ) è avere la calda sensazione che le etichette vadano insieme alle trame esatte che pensi che facciano:

...
# 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 non funziona


3
A proposito: puoi anche usare l'etichetta "kwarg" per tracciare e poi chiamare legenda senza alcun argomento.
Joe Kington,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.