¿Duplicar elementos en leyenda en matplotlib?

Estoy intentando agregar la leyenda a mi ttwig con este fragmento de código:

import matplotlib.pylab as plt fig = plt.figure() axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1) axes.set_xlabel('x (m)') axes.set_ylabel('y (m)') for i, representative in enumerate(representatives): axes.plot([e[0] for e in representative], [e[1] for e in representative], color='b', label='Representatives') axes.scatter([e[0] for e in intersections], [e[1] for e in intersections], color='r', label='Intersections') axes.legend() 

Termino con esta ttwig.

introduzca la descripción de la imagen aquí

Obviamente, los elementos están duplicados en la ttwig. ¿Cómo puedo corregir este error?

Como dicen los documentos , aunque es fácil perderse:

Si el atributo label es una cadena vacía o comienza con “_”, esos artistas serán ignorados.

Entonces, si estoy trazando líneas similares en un bucle y solo quiero una línea de ejemplo en la leyenda, generalmente hago algo como

 ax.plot(x, y, label="Representatives" if i == 0 else "") 

donde i es mi índice de bucle.

No es tan agradable verlos como construirlos por separado, pero a menudo quiero mantener la lógica de la etiqueta lo más cerca posible del dibujo de líneas.

(Tenga en cuenta que los desarrolladores de matplotlib tienden a usar "_nolegend_" para ser explícitos).

Aquí hay un método para eliminar las entradas de leyenda duplicadas después de asignar tags normalmente:

 representatives=[[[-100,40],[-50,20],[0,0],[75,-5],[100,5]], #made up some data [[-60,80],[0,85],[100,90]], [[-60,15],[-50,90]], [[-2,-2],[5,95]]] fig = plt.figure() axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1) axes.set_xlabel('x (m)') axes.set_ylabel('y (m)') for i, representative in enumerate(representatives): axes.plot([e[0] for e in representative], [e[1] for e in representative],color='b', label='Representatives') #make sure only unique labels show up (no repeats) handles,labels=axes.get_legend_handles_labels() #get existing legend item handles and labels i=arange(len(labels)) #make an index for later filter=array([]) #set up a filter (empty for now) unique_labels=tolist(set(labels)) #find unique labels for ul in unique_labels: #loop through unique labels filter=np.append(filter,[i[array(labels)==ul][0]]) #find the first instance of this label and add its index to the filter handles=[handles[int(f)] for f in filter] #filter out legend items to keep only the first instance of each repeated label labels=[labels[int(f)] for f in filter] axes.legend(handles,labels) #draw the legend with the filtered handles and labels lists 

Y aquí están los resultados: introduzca la descripción de la imagen aquí A la izquierda está el resultado del script anterior. A la derecha, la llamada a la leyenda ha sido reemplazada por axes.legend() .

La ventaja es que puede pasar por la mayoría de su código y simplemente asignar tags normalmente y no preocuparse por los bucles en línea o if es así. También puedes construir esto en un envoltorio alrededor de la leyenda o algo así.

Esto no es un error. Su etiqueta dentro del bucle for está agregando len(representatives)-1 tags repetitivas a su leyenda. ¿Y si en vez de eso hiciste algo como?

 for i, representative in enumerate(representatives): rep, = axes.plot([e[0] for e in representative], [e[1] for e in representative], color='b') inter = axes.scatter([e[0] for e in intersections], [e[1] for e in intersections], color='r') axes.legend((rep, inter), ("Representatives", "Intersections")) 

Edición: el formato del código siguiente utiliza el formato publicado en el tutorial de leyendas de matplotlib . La razón por la que falló el código anterior es porque faltaba una coma después de rep, = . Cada iteración, la rep se sobrescribe y cuando se usa para llamar legend , solo la última representación de representantes se almacena en la rep .

 fig = plt.figure() ax = fig.add_subplot(111) for i, representative in enumerate(representatives): rep, = ax.plot([e[0] for e in representative], [e[1] for e in representative], color='b') inter = ax.scatter([e[0] for e in intersections], [e[1] for e in intersections], color='r') ax.legend((rep, inter), ("Representatives", "Intersections")) 

También puede intentar trazar sus datos de la manera que lo hace en su OP, pero hacer la leyenda usando

 handles, labels = ax.get_legend_handles_labels() 

y editando los contenidos de los handles y labels .