Подтвердить что ты не робот

Matplotlib: 2 разных легенды на одном графике

У меня есть график, в котором для разных параметров используются разные цвета, а для разных алгоритмов используются разные стили линий. Целью является сравнение результатов различных алгоритмов, выполняемых с аналогичными параметрами. Это означает, что в общей сложности я использую 4 разных цвета и 3 разных стиля линий, в общей сложности 12 графиков на одном графике.

Я фактически создаю легенду на основе цветов, сопоставляя каждый цвет с соответствующим параметром. Теперь я хотел бы отобразить вторую легенду на том же графике со значением каждого стиля линии. Этого можно достичь? Как?

Вот как выглядит мой код:

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

Ответ 1

В документации matplotlib по этому предмету есть раздел: http://matplotlib.org/users/legend_guide.html#multiple-legends-on-the-same-axes

Здесь код для вашего конкретного примера:

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)

Здесь пример его вывода: Plot with 2 legends, per-param and per-algo

Ответ 2

Здесь также более "практический" способ сделать это (т.е. явно взаимодействовать с любыми осями фигур):

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)

Мне нравится этот способ написания, так как он позволяет потенциально играть с разными осями менее неясным образом. Вы можете сначала создать свой набор легенд, а затем добавить их к осям, которые вы хотите, с помощью метода "add_artist". Кроме того, я начинаю с matplotlib, и для меня, по крайней мере, легче понять скрипты, когда objets объясняются.

Примечание. Будьте осторожны, ваши легенды могут быть обрезаны при отображении/сохранении. Чтобы решить эту проблему, используйте метод axes.set_position ([left, bottom, width, length]), чтобы уменьшить размер шрифта относительно размера фигуры и сделать легенды.