2012-03-23 11 views
72

Sto tracciando lo stesso tipo di informazioni, ma per paesi diversi, con sottotrame multiple con matplotlib. Cioè, ho 9 grafici su una griglia 3x3, tutti con lo stesso per le linee (ovviamente, valori diversi per linea).come si crea una singola legenda per molte sottotrame con matplotlib?

Tuttavia, non ho capito come mettere una sola legenda (dato che tutte e 9 le sottotrame hanno le stesse linee) sulla figura solo una volta.

Come posso fare?

risposta

68

figlegend può essere quello che stai cercando: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.figlegend

Esempio qui: http://matplotlib.org/examples/pylab_examples/figlegend_demo.html

Un altro esempio:

plt.figlegend(lines, labels, loc = 'lower center', ncol=5, labelspacing=0.) 

o:

fig.legend(lines, labels, loc = (0.5, 0), ncol=5) 
+1

Conosco le righe che voglio inserire nella legenda, ma come faccio a ottenere la variabile 'lines' per inserire l'argomento per' legend'? –

+1

@patapouf_ai 'lines' è un elenco di risultati restituiti da' axes.plot() '(ad esempio, ogni' axes.plot' o una routine simile restituisce una "linea"). Vedi anche l'esempio collegato. – Evert

13

Devi solo chiedi la leggenda una volta, al di fuori del tuo ciclo.

Ad esempio, in questo caso ho 4 sottotrame, con le stesse linee e una singola legenda.

from matplotlib.pyplot import * 

ficheiros = ['120318.nc', '120319.nc', '120320.nc', '120321.nc'] 

fig = figure() 
fig.suptitle('concentration profile analysis') 

for a in range(len(ficheiros)): 
    # dados is here defined 
    level = dados.variables['level'][:] 

    ax = fig.add_subplot(2,2,a+1) 
    xticks(range(8), ['0h','3h','6h','9h','12h','15h','18h','21h']) 
    ax.set_xlabel('time (hours)') 
    ax.set_ylabel('CONC ($\mu g. m^{-3}$)') 

    for index in range(len(level)): 
     conc = dados.variables['CONC'][4:12,index] * 1e9 
     ax.plot(conc,label=str(level[index])+'m') 

    dados.close() 

ax.legend(bbox_to_anchor=(1.05, 0), loc='lower left', borderaxespad=0.) 
     # it will place the legend on the outer right-hand side of the last axes 

show() 
+3

'figlegend', come suggerito da Evert, sembra essere una soluzione molto migliore;) – carla

+10

il problema di' fig.legend() 'è che richiede l'identificazione per tutte le linee (grafici) ... come, per ogni sottotrama , Sto usando un loop per generare le linee, l'unica soluzione che ho capito per ovviare a questo è creare una lista vuota prima del secondo ciclo, e quindi aggiungere le linee mentre vengono create ... Quindi uso questa lista come un argomento alla funzione 'fig.legend()'. – carla

+0

Una domanda simile [qui] (https://stackoverflow.com/questions/22001756/one-legend-for-all-subplots-in-pyplot) –

12

Per il posizionamento automatico di un singolo legenda in una figure con molti assi, come quelli ottenuti con subplots(), la seguente soluzione funziona molto bene:

plt.legend(lines, labels, loc = 'lower center', bbox_to_anchor = (0,-0.1,1,1), 
      bbox_transform = plt.gcf().transFigure) 

Con bbox_to_anchor e bbox_transform=plt.gcf().transFigure si definisce un nuovo riquadro di delimitazione delle dimensioni del tuo figure come riferimento per loc. L'utilizzo di (0,-0.1,1,1) sposta questo riquadro verso il basso leggermente per evitare che la legenda venga posizionata su altri artisti.

OBS: utilizzare questa soluzione dopo aver utilizzato fig.set_size_inches() e prima di utilizzare fig.tight_layout()

+1

O simpy 'loc = 'centro superiore', bbox_to_anchor = (0.5, 0), bbox_transform = plt.gcf(). TransFigure' e non si sovrapporrà di sicuro. –

+1

Non sono ancora sicuro del perché, ma la soluzione di Evert non ha funzionato per me - la leggenda ha continuato a venire interrotta. Questa soluzione (insieme al commento di davor) ha funzionato in modo molto pulito: la leggenda è stata posizionata come previsto e completamente visibile. Grazie! –

7

C'è anche una bella funzione get_legend_handles_labels() è possibile chiamare l'ultimo asse (se di eseguire iterazioni su di loro) che raccolga tutto il necessario da label= argomenti:

handles, labels = ax.get_legend_handles_labels() 
fig.legend(handles, labels, loc='upper center') 
+1

Questa dovrebbe essere la risposta migliore. – naught101

0

Questa risposta è un complemento @ Evert è sulla posizione di leggenda.

Il mio primo tentativo su @ soluzione di Evert è fallito a causa di sovrapposizioni della leggenda e del titolo della sottotrama.

In realtà, le sovrapposizioni sono causate da fig.tight_layout(), che modifica il layout delle sottotrame senza considerare la legenda della figura. Tuttavia, è necessario fig.tight_layout().

Per evitare sovrapposizioni, è possibile comunicare allo fig.tight_layout() di lasciare spazi per la legenda della figura tramite fig.tight_layout(rect=(0,0,1,0.9)).

Description of tight_layout() parameters.

Problemi correlati