2014-06-12 20 views
30

Dire che ho dati su 3 strategie di trading, ciascuna con e senza costi di transazione. Voglio tracciare, sugli stessi assi, le serie temporali di ognuna delle 6 varianti (3 strategie * 2 costi di trading). Vorrei che le linee "con costo di transazione" venissero tracciate con alpha=1 e linewidth=1 mentre voglio che il "nessun costo di transazione" venga tracciato con alpha=0.25 e linewidth=5. Ma vorrei che il colore fosse lo stesso per entrambe le versioni di ciascuna strategia.Ripristino ciclo colore in Matplotlib

Vorrei qualcosa sulla falsariga di:

fig, ax = plt.subplots(1, 1, figsize=(10, 10)) 

for c in with_transaction_frame.columns: 
    ax.plot(with_transaction_frame[c], label=c, alpha=1, linewidth=1) 

****SOME MAGIC GOES HERE TO RESET THE COLOR CYCLE 

for c in no_transaction_frame.columns: 
    ax.plot(no_transaction_frame[c], label=c, alpha=0.25, linewidth=5) 

ax.legend() 

Qual è il codice appropriato per mettere sulla linea indicata per ripristinare il ciclo di colore, quindi è "di nuovo al punto di partenza", quando il secondo ciclo è invocato?

+0

Matplotlib è stato modificato dall'ultima risposta alla domanda. Ti dispiacerebbe cambiare la risposta accettata per riflettere la versione più recente? – Seanny123

risposta

45

È possibile reimpostare il colorcycle per l'originale con Axes.set_color_cycle. Guardando il codice per questo, v'è una funzione per fare il lavoro vero e proprio:

def set_color_cycle(self, clist=None): 
    if clist is None: 
     clist = rcParams['axes.color_cycle'] 
    self.color_cycle = itertools.cycle(clist 

E un metodo sugli assi che lo usa:

def set_color_cycle(self, clist): 
    """ 
    Set the color cycle for any future plot commands on this Axes. 

    *clist* is a list of mpl color specifiers. 
    """ 
    self._get_lines.set_color_cycle(clist) 
    self._get_patches_for_fill.set_color_cycle(clist) 

Ciò significa che si può chiamare la set_color_cycle con Nessuno come unico argomento e verrà sostituito con il ciclo predefinito trovato in rcParams ['axes.color_cycle'].

Ho provato questo con il seguente codice ed ha ottenuto il risultato atteso:

import matplotlib.pyplot as plt 
import numpy as np 

for i in range(3): 
    plt.plot(np.arange(10) + i) 

plt.gca().set_color_cycle(None) 

for i in range(3): 
    plt.plot(np.arange(10, 1, -1) + i) 

plt.show() 

Code output, showing the color cycling reset functionality

+1

Vorrei sopravvivere questa dozzina di volte se potessi. – 8one6

+0

Grazie @ 8one6. Matplotlib è incredibilmente potente quando sai come - penso che il vero problema è che il potere non documenta così bene, quindi IMHO è una competenza davvero importante con i pacchetti Python open source è quella di essere in grado di seguire l'effettiva implementazione/codice.Non è così complicato - immagino sia semplicemente scoraggiante fare la prima volta ... – pelson

+13

Dato che Matplotlib 1.5.0, 'set_color_cycle' è deprecato e non accetta più' Nessuno'! Fortunatamente, la nuova (più ampia) alternativa 'set_prop_cycle' * fa * accetta 'None' ancora ... – burnpanck

2

Basta scegliere i colori e assegnarli a un elenco, quindi quando si tracciano i dati iterare su un oggetto zip contenente la colonna e il colore desiderato.

colors = ['red', 'blue', 'green'] 

for col, color in zip(colors, with_transaction_frame.columns): 
    ax.plot(with_transaction_frame[col], label=col, alpha=1.0, linewidth=1.0, color=color) 

for col, color in zip(no_transaction_frame.columns): 
    ax.plot(no_transaction_frame[col], label=col, alpha=0.25, linewidth=5, color=color) 

zip crea un elenco che aggrega gli elementi da ciascuno dei vostre liste. Questo ti permette di scorrere entrambi facilmente allo stesso tempo.

+0

potresti effettivamente creare quell'elenco di colori chiamando 'get_color' sul ritorno di' ax.plot' nel primo ciclo. – M4rtini

+0

Tipo di aggirare la domanda. Nel mio caso, sto lavorando con 'seaborn' e, in generale, potrebbe esserci una tavolozza di colori complicata come predefinita. Non voglio scoparmelo. Voglio solo tracciare due volte lo stesso ciclo di colori usato ogni volta ... senza bisogno di sapere quale ciclo di colore è in anticipo. – 8one6

+0

Ok abbastanza bene :) non è una vera e propria spunto per la domanda in quanto è una risposta perfettamente valida e semplice alla domanda, come hai affermato, ma se stai usando Seaborn, allora posso vedere come non vorrai rovinare colori scegliendoli manualmente. In questo caso, farei come @ suggerisce M4rtini e usare 'get_color' per ottenere i colori dalla prima iterazione del disegno e usarli nel 2 °, forse potrebbero volerli scrivere come risposta per te. – Ffisegydd

4

Dal momento che lei ha citato si sta utilizzando Seaborn, quello che mi sento di raccomandare facendo è:

with sns.color_palette(n_colors=3): 

    ax.plot(...) 
    ax.plot(...) 

Questo imposterà la tavolozza dei colori per utilizzare il ciclo di colore attualmente attivo, ma solo i primi tre colori da esso. È anche una soluzione generica per ogni momento in cui desideri impostare un ciclo di colore temporaneo.

Nota che l'unica cosa che ha bisogno in realtà di essere sotto il blocco with è tutto ciò che si sta facendo per creare l'oggetto Axes (cioè plt.subplots, fig.add_subplot(), etc.). Questo è solo a causa di come funziona il ciclo del colore matplotlib.

Fare ciò che si vuole, "resettare" il ciclo del colore, è possibile, ma è un trucco e non lo farei in alcun tipo di codice di produzione. Qui, però, è come potrebbe accadere:

f, ax = plt.subplots() 
ax.plot(np.random.randn(10, 3)) 
ax._get_lines.color_cycle = itertools.cycle(sns.color_palette()) 
ax.plot(np.random.randn(10, 3), lw=5, alpha=.25) 

enter image description here

+0

Grazie per aver dedicato del tempo per scrivere questa risposta. Capisco che questo funzionerà perché so a priori che tratterò 3 serie usando ciascuno dei comandi 'ax.plot' sopra. Ma sai se esiste un modo generale per "resettare" il ciclo del colore in un dato punto del codice? Senza una conoscenza specifica di cosa sia il ciclo del colore (o quale sia il suo stato) nel punto in cui viene emesso il comando? – 8one6

+1

È possibile farlo, ma è un trucco che non raccomanderei davvero. Vedi modifica per rispondere. – mwaskom

+1

Vorrei anche sottolineare che dovresti sempre essere in grado di dedurre quanti colori hai bisogno dai dati. – mwaskom

2

è possibile ottenere i colori da Seaborn in questo modo: colors = sns.color_palette().La risposta di Ffisegydd funzionerebbe alla grande. È anche possibile ottenere il colore da tracciare usando l'operatore modulo/resto (%): mycolor = colors[icolumn % len(colors]. Io uso spesso questo approccio da solo. Così si potrebbe fare:

for icol, column in enumerate(with_transaction_frame.columns): mycolor = colors[icol % len(colors] ax.plot(with_transaction_frame[col], label=col, alpha=1.0, color=mycolor)

risposta di Ffisegydd potrebbe essere piu 'divinatorio', però.

12

Come la risposta data da @pelson utilizza set_color_cycle e questo è deprecato in Matplotlib 1.5, ho pensato che sarebbe stato utile avere una versione aggiornata della sua soluzione con set_prop_cycle:

import matplotlib.pyplot as plt 
import numpy as np 

for i in range(3): 
    plt.plot(np.arange(10) + i) 

plt.gca().set_prop_cycle(None) 

for i in range(3): 
    plt.plot(np.arange(10, 0, -1) + i) 

plt.show() 

Nota anche che ho avuto per cambiare np.arange(10,1,-1) a np.arange(10,0,-1). Il primo ha fornito una serie di soli 9 elementi. Questo probabilmente deriva dall'uso di diverse versioni di Numpy. Il mio è 1.10.2.

MODIFICA: Rimossa la necessità di utilizzare rcParams. Grazie a @divenex per averlo indicato in un commento.

+1

Contrariamente a quanto affermato in questa risposta' plt.gca(). Set_prop_cycle (None) 'funziona da Matplotlib 1.5 (come sottolineato by @burnpanck) e ho appena verificato che funzioni anche in Matplotlib 2.0. – divenex

+0

"deprecato" significa che verrà rimosso in futuro, anche se funziona nella versione corrente. Vedi http://matplotlib.org/devdocs/api/_as_gen/matplotlib.axes.Axes.set_color_cycle.html –

+1

Il mio commento non riguarda la deprecazione, ma il fatto che non è necessario specificare il ciclatore in 'set_prop_cycle' . – divenex

Problemi correlati