2016-06-03 25 views
5

Avevo già fatto una domanda su come tracciare colonne diverse da un dataframe di panda su sottotrame separate qui: Plot multiple lines on subplots with pandas df.plot, e ho ottenuto un'ottima risposta. Ora sto cercando di massimizzare l'uso dello spazio sulla trama e la leggenda si sta rivelando un problema. Quello che mi piacerebbe fare è mettere 3 o 4 serie su una legenda e le rimanenti sull'altra, in modo che io possa mettere ciascuna in un angolo, dove si adatteranno bene.Sottotitoli multiplo di Legends su Pandas df.plot?

ho cercato di utilizzare i metodi descritti per matplotlib, mostrato qui:

from matplotlib.pyplot import * 

p1, = plot([1,2,3], label="test1") 
p2, = plot([3,2,1], label="test2") 

l1 = legend([p1], ["Label 1"], loc=1) 
l2 = legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
gca().add_artist(l1) # add l1 as a separate artist to the axes 

show() 

ma, sto ottenendo le questioni che sono o di utilizzare il df.plot panda, o dal tentativo di implementare su una sottotrama . Ecco quello che ho provato:

f, (ax1, ax2) = plt.subplots(ncols = 2) 

p1 = dfcomb.iloc[:,:3].plot(ax=ax1, figsize=(14,5)) 
p2 = dfcomb.iloc[:,3:6].plot(ax=ax1, figsize=(14,5)) 
l1 = ax1.legend([p1], ["Label 1"], loc=1) 
l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
gca().add_artist(l1) # add l1 as a separate artist to the axes 

ed ecco cosa ottengo:

--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-108-d3206d8ce17d> in <module>() 
    15 l1 = ax1.legend([p1], ["Label 1"], loc=1) 
    16 l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
---> 17 gca().add_artist(l1) 
    18 
    19 ax1.set_xlabel('Suction (cm)') 

C:\Anaconda\lib\site-packages\matplotlib\axes\_base.pyc in add_artist(self, a) 
    1646   Returns the artist. 
    1647   """ 
-> 1648   a.axes = self 
    1649   self.artists.append(a) 
    1650   self._set_artist_props(a) 

C:\Anaconda\lib\site-packages\matplotlib\artist.pyc in axes(self, new_axes) 
    235   if (new_axes is not None and 
    236     (self._axes is not None and new_axes != self._axes)): 
--> 237    raise ValueError("Can not reset the axes. You are " 
    238        "probably trying to re-use an artist " 
    239        "in more than one Axes which is not " 

ValueError: Can not reset the axes. You are probably trying to re-use an artist in more than one Axes which is not supported 

Qualcuno ha un work-around?

risposta

4

Sei stato imboscato da una falsa ipotesi sulla natura di gca(). Anch'io sono rimasto sorpreso, motivo per cui ho deciso di aggiungere una risposta (altrimenti parliamo principalmente di un problema di battitura a macchina). Inoltre, noto che il problema non ha nulla a che fare con i panda.

Ecco un esempio minimo che riproduce il problema senza panda:

import matplotlib.pyplot as plt 

f, (ax1, ax2) = plt.subplots(ncols = 2) 
p1, = ax1.plot([1,2,3], label="test1") 
p2, = ax1.plot([3,2,1], label="test2") 

l1 = ax1.legend([p1], ["Label 1"], loc=1) 
l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
plt.gca().add_artist(l1) 

Allora qual è il problema? Date un'occhiata più da vicino al messaggio di errore:

ValueError: Can not reset the axes. You are probably trying to re-use an artist in more than one Axes which is not supported

(enfasi mia). Guardate:

>>> ax1 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd83abf7e10> 
>>> ax2 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd83a992850> 
>>> plt.gca() 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd83a992850> 

Il problema è che anche se si sta lavorando ax1, i "grafica assi correnti" note anche come gca() indica ax2, il Axes creato ultima.

La soluzione ora è semplice: essere esplicito con la chiamata ridisegno (ricordate, esplicito è meglio che implicita):

import matplotlib.pyplot as plt 

f, (ax1, ax2) = plt.subplots(ncols = 2) 
p1, = ax1.plot([1,2,3], label="test1") 
p2, = ax1.plot([3,2,1], label="test2") 
# or whatever plots you prefer using pandas 
# (I'd use matplotlib directly anyway) 

l1 = ax1.legend([p1], ["Label 1"], loc=1) 
l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
ax1.add_artist(l1) # <-- just change here, refer to ax1 explicitly 

Ed è vivo!

result

+1

che fa un sacco di senso, e tendo a concordare con la visualizzazione di essere esplicito. Sarebbe bello se anche l'esempio matplotlib fosse esplicito. Ri: usando direttamente matplotlib - Ho trovato che i panda progettano di essere gentili in termini di flusso di lavoro per tracciare un gran numero di serie, cose del genere. Grazie! – spizwhiz

+0

@spizwhiz grazie per il feedback, non ho molta dimestichezza con i panda, ma ho già visto alcuni problemi che sono stati risolti usando 'plt.plot'. Ovviamente dovresti usare quello che funziona per te. E il fatto di essere espliciti è incluso in [Zen of Python] (https://www.python.org/dev/peps/pep-0020/) :) –