2014-10-13 24 views
11

Mam dane, które skutkują wykreślaniem wielu linii, chcę nadać tym wierszom jedną etykietę w mojej legendzie. Myślę, że to może być lepiej wykazać stosując poniższy przykład,Pyplot łączą wiele etykiet linii w legendzie

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

Jak widać na Out [23] fabuła doprowadziły 5 różnych linii. Wynikowa działka wygląda tak, jakby to był jeden sposób, w jaki mogę określić metodę drukowania, aby uniknąć wielu etykiet? Nie chcę używać niestandardowej legendy (gdzie określasz etykietę i kształt linii naraz) w największym możliwym stopniu.

+1

Trzeba dziennik celu stworzenie własnego legendę. Nie można wkleić linku, ponieważ mój telefon jest bzdura. Google "matplotlib ręcznie stworzyć legendę". Istnieje odpowiedź SO, która ma wszystko, czego potrzebujesz, kilka trafień w dół. – will

+0

@ dzięki, to jest pomocne – hashmuke

Odpowiedz

8

Chciałbym zrobić małą funkcję pomocnika osobiście, jeśli planowałem robić to często;

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

Łatwiej (i IMO jaśniejsze) sposób, aby usunąć duplikaty (niż to co masz) z handles i labels legendy jest to:

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

Więc stosując sugestię będzie i kolejne pytanie here, wyjeżdżam moje lekarstwo tutaj

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) 

A nowa fabuła wygląda, modified multiple line plot legend

4

matplotlib daje ładny interfejs do zbiorów linii, LineCollection. Kod jest prosta

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

Wynika to w poniższej wyjścia: A plot of the lines collected under a single legend entry.

4

rozwiązania NumPy oparciu o odpowiedź będzie za powyżej.

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

Zakładając, że równe etykiety mają równe uchwyty, uzyskać unikalne etykiety i ich odpowiednie wskaźniki, które odpowiadają sobie indeksy.

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

Niskim rozwiązaniem technicznym jest wykonanie dwóch połączeń fabularnych. Jeden, że działki danych i drugi, że działki nic ale niesie rękojeść:

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

Oto wynik:

result