matplotlib: 2 leyendas diferentes en el mismo gráfico

Tengo un gráfico donde se usan diferentes colores para diferentes parámetros, y donde se usan diferentes estilos de línea para diferentes algoritmos. El objective es comparar los resultados de los diferentes algoritmos realizados con parámetros similares. Significa que, en total, uso 4 colores diferentes y 3 estilos de línea diferentes, para un total de 12 gráficos en el mismo gráfico.

De hecho, construyo la leyenda basada en colores, asociando cada color con el parámetro correspondiente. Ahora me gustaría mostrar una segunda leyenda en el mismo gráfico, con el significado de cada estilo de línea. ¿Es posible lograr eso? ¿Cómo?

Aquí es como se ve mi código en realidad:

colors = ['b', 'r', 'g', 'c'] cc = cycle(c) for p in parameters: d1 = algo1(p) d2 = algo2(p) d3 = algo3(p) pyplot.hold(True) c = next(cc) pyplot.plot(d1, '-', color=c, label="d1") pyplot.plot(d1, '--', color=c) pyplot.plot(d2, '.-', color=c) pyplot.legend() 

Hay una sección en la documentación de matplotlib sobre ese tema exacto: http://matplotlib.org/users/legend_guide.html#multiple-legends-on-the-same-axes

Aquí está el código para su ejemplo específico:

 import itertools from matplotlib import pyplot colors = ['b', 'r', 'g', 'c'] cc = itertools.cycle(colors) plot_lines = [] for p in parameters: d1 = algo1(p) d2 = algo2(p) d3 = algo3(p) pyplot.hold(True) c = next(cc) l1, = pyplot.plot(d1, '-', color=c) l2, = pyplot.plot(d2, '--', color=c) l3, = pyplot.plot(d3, '.-', color=c) plot_lines.append([l1, l2, l3]) legend1 = pyplot.legend(plot_lines[0], ["algo1", "algo2", "algo3"], loc=1) pyplot.legend([l[0] for l in plot_lines], parameters, loc=4) pyplot.gca().add_artist(legend1) 

Aquí hay un ejemplo de su salida: Parcela con 2 leyendas, per-param y per-algo.

Aquí también hay una forma más “práctica” de hacerlo (es decir, interactuar explícitamente con los ejes de cualquier figura):

 import itertools from matplotlib import pyplot fig, axes = plt.subplot(1,1) colors = ['b', 'r', 'g', 'c'] cc = itertools.cycle(colors) plot_lines = [] for p in parameters: d1 = algo1(p) d2 = algo2(p) d3 = algo3(p) c = next(cc) axes.plot(d1, '-', color=c) axes.plot(d2, '--', color=c) axes.plot(d3, '.-', color=c) # In total 3x3 lines have been plotted lines = axes.get_lines() legend1 = pyplot.legend([lines[i] for i in [0,1,2]], ["algo1", "algo2", "algo3"], loc=1) legend2 = pyplot.legend([lines[i] for i in [0,3,6]], parameters, loc=4) axes.add_artist(legend1) axes.add_artist(legend2) 

Me gusta esta forma de escribirlo, ya que potencialmente permite jugar con diferentes ejes de una manera menos oscura. Primero puede crear su conjunto de leyendas y luego agregarlas a los ejes que desee con el método “add_artist”. Además, estoy empezando con matplotlib y, al menos para mí, es más fácil comprender los scripts cuando se explican los objetos.

NB: Tenga cuidado, sus leyendas pueden estar cortadas mientras se muestra / se guarda. Para resolver este problema, use el método axes.set_position ([left, bottom, width, length]) para reducir la ttwig secundaria en relación con el tamaño de la figura y hacer que aparezcan las leyendas.