2014-10-13 13 views
11

Ho dati che determinano il tracciamento di più linee, voglio dare a queste righe un'etichetta singola nella mia legenda. Credo che questo possa essere meglio dimostrata utilizzando l'esempio di seguito,pyplot combina più etichette di linea nella legenda

a = np.array([[ 3.57, 1.76, 7.42, 6.52], 
       [ 1.57, 1.2 , 3.02, 6.88], 
       [ 2.23, 4.86, 5.12, 2.81], 
       [ 4.48, 1.38, 2.14, 0.86], 
       [ 6.68, 1.72, 8.56, 3.23]]) 

plt.plot(a[:,::2].T, a[:, 1::2].T, 'r', label='data_a') 

plt.legend(loc='best') 

Come si può vedere in Out [23] la trama ha portato in 5 linee distinte. Il grafico risultante assomiglia a questo legend of multiple line plot

C'è un modo che posso dire al metodo di stampa per evitare più etichette? Non voglio usare la legenda personalizzata (dove si specifica l'etichetta e la forma della linea tutto in una volta) il più possibile.

+1

È necessario telegiornale per creare una leggenda personalizzato. Impossibile incollare un collegamento perché il mio telefono si sta schifo. Google "matplotlib crea manualmente una legenda". C'è una risposta SO che ha tutto ciò che ti serve un paio di colpi in basso. – will

+0

@ grazie, è utile – hashmuke

risposta

8

mi piacerebbe fare un piccolo funzione di supporto personalmente, se ho programmato di farlo spesso;

from matplotlib import pyplot 
import numpy 


a = numpy.array([[ 3.57, 1.76, 7.42, 6.52], 
       [ 1.57, 1.2 , 3.02, 6.88], 
       [ 2.23, 4.86, 5.12, 2.81], 
       [ 4.48, 1.38, 2.14, 0.86], 
       [ 6.68, 1.72, 8.56, 3.23]]) 


def plotCollection(ax, xs, ys, *args, **kwargs): 

    ax.plot(xs,ys, *args, **kwargs) 

    if "label" in kwargs.keys(): 

    #remove duplicates 
    handles, labels = pyplot.gca().get_legend_handles_labels() 
    newLabels, newHandles = [], [] 
    for handle, label in zip(handles, labels): 
     if label not in newLabels: 
     newLabels.append(label) 
     newHandles.append(handle) 

    pyplot.legend(newHandles, newLabels) 

ax = pyplot.subplot(1,1,1) 
plotCollection(ax, a[:,::2].T, a[:, 1::2].T, 'r', label='data_a') 
plotCollection(ax, a[:,1::2].T, a[:, ::2].T, 'b', label='data_b') 
pyplot.show() 

Un modo più semplice (e IMO più chiaro) per rimuovere i duplicati (rispetto a quello che hai) dal handles e labels della leggenda è questo:

handles, labels = pyplot.gca().get_legend_handles_labels() 
newLabels, newHandles = [], [] 
for handle, label in zip(handles, labels): 
    if label not in newLabels: 
    newLabels.append(label) 
    newHandles.append(handle) 
pyplot.legend(newHandles, newLabels) 
6

Quindi, utilizzando il suggerimento di volontà e un'altra domanda here, lascio il mio rimedio qui

handles, labels = plt.gca().get_legend_handles_labels() 
i =1 
while i<len(labels): 
    if labels[i] in labels[:i]: 
     del(labels[i]) 
     del(handles[i]) 
    else: 
     i +=1 

plt.legend(handles, labels) 

E la nuova trama assomiglia, modified multiple line plot legend

4

Matplotlib ti dà una bella interfaccia alle collezioni di linee, LineCollection. Il codice è semplice

import numpy 
import matplotlib.pyplot as plt 
from matplotlib.collections import LineCollection 

a = numpy.array([[ 3.57, 1.76, 7.42, 6.52], 
       [ 1.57, 1.2 , 3.02, 6.88], 
       [ 2.23, 4.86, 5.12, 2.81], 
       [ 4.48, 1.38, 2.14, 0.86], 
       [ 6.68, 1.72, 8.56, 3.23]]) 

xs = a[:,::2] 
ys = a[:, 1::2] 
lines = LineCollection([list(zip(x,y)) for x,y in zip(xs, ys)], label='data_a') 
f, ax = plt.subplots(1, 1) 
ax.add_collection(lines) 
ax.legend() 
ax.set_xlim([xs.min(), xs.max()]) # have to set manually 
ax.set_ylim([ys.min(), ys.max()]) 
plt.show() 

Ciò comporta l'output di seguito: A plot of the lines collected under a single legend entry.

4

soluzione Numpy base alla risposta di volontà sopra.

import numpy as np 
import matplotlib.pylab as plt 
a = np.array([[3.57, 1.76, 7.42, 6.52], 
       [1.57, 1.20, 3.02, 6.88], 
       [2.23, 4.86, 5.12, 2.81], 
       [4.48, 1.38, 2.14, 0.86], 
       [6.68, 1.72, 8.56, 3.23]]) 

plt.plot(a[:,::2].T, a[:, 1::2].T, 'r', label='data_a') 
handles, labels = plt.gca().get_legend_handles_labels() 

Supponendo che uguali etichette hanno maniglie uguali, ottenere etichette uniche e rispettivi indici, che corrispondono a gestire indici.

labels, ids = np.unique(labels, return_index=True) 
handles = [handles[i] for i in ids] 
plt.legend(handles, labels, loc='best') 
plt.show() 
0

Una soluzione a bassa tecnologia consiste nel fare due chiamate di trama. Uno che traccia i dati e un secondo che traccia nulla, ma porta la maniglia:

a = np.array([[ 3.57, 1.76, 7.42, 6.52], 
       [ 1.57, 1.2 , 3.02, 6.88], 
       [ 2.23, 4.86, 5.12, 2.81], 
       [ 4.48, 1.38, 2.14, 0.86], 
       [ 6.68, 1.72, 8.56, 3.23]]) 

plt.plot(a[:,::2].T, a[:, 1::2].T, 'r') 
plt.plot([],[], 'r', label='data_a') 

plt.legend(loc='best') 

Ecco il risultato:

result

Problemi correlati