как сделать одну легенду для многих сюжетов с помощью matplotlib? - PullRequest
119 голосов
/ 23 марта 2012

Я строю информацию одного и того же типа, но для разных стран, с несколькими участками с matplotlib.То есть у меня есть 9 графиков на сетке 3х3, все с одинаковым для линий (конечно, разные значения на линию).

Тем не менее, я не выяснил, как разместить на рисунке одну легенду (так как все 9 сюжетов имеют одинаковые линии) только один раз.

Как мне это сделать?

Ответы [ 7 ]

97 голосов
/ 23 марта 2012

figlegend может быть тем, что вы ищете: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.figlegend

Пример здесь: http://matplotlib.org/examples/pylab_examples/figlegend_demo.html

Другой пример:

plt.figlegend( lines, labels, loc = 'lower center', ncol=5, labelspacing=0. )

или

fig.legend( lines, labels, loc = (0.5, 0), ncol=5 )
74 голосов
/ 25 октября 2017

Есть также хорошая функция get_legend_handles_labels(), которую вы можете вызвать по последней оси (если вы выполните итерацию по ним), которая будет собирать все, что вам нужно, из label= аргументов:

handles, labels = ax.get_legend_handles_labels()
fig.legend(handles, labels, loc='upper center')
15 голосов
/ 23 марта 2012

Вы просто должны попросить легенду один раз, вне вашей петли.

Например, в этом случае у меня есть 4 вспомогательных участка с одинаковыми строками и одной легендой.

from matplotlib.pyplot import *

ficheiros = ['120318.nc', '120319.nc', '120320.nc', '120321.nc']

fig = figure()
fig.suptitle('concentration profile analysis')

for a in range(len(ficheiros)):
    # dados is here defined
    level = dados.variables['level'][:]

    ax = fig.add_subplot(2,2,a+1)
    xticks(range(8), ['0h','3h','6h','9h','12h','15h','18h','21h']) 
    ax.set_xlabel('time (hours)')
    ax.set_ylabel('CONC ($\mu g. m^{-3}$)')

    for index in range(len(level)):
        conc = dados.variables['CONC'][4:12,index] * 1e9
        ax.plot(conc,label=str(level[index])+'m')

    dados.close()

ax.legend(bbox_to_anchor=(1.05, 0), loc='lower left', borderaxespad=0.)
         # it will place the legend on the outer right-hand side of the last axes

show()
14 голосов
/ 26 июня 2013

Для автоматического позиционирования одной легенды в figure со многими осями, подобно полученным с subplots(), очень хорошо работает следующее решение:

plt.legend( lines, labels, loc = 'lower center', bbox_to_anchor = (0,-0.1,1,1),
            bbox_transform = plt.gcf().transFigure )

С bbox_to_anchor и bbox_transform=plt.gcf().transFigure вы определяете новую ограничивающую рамку размером вашего figure как ссылку для loc.Использование (0,-0.1,1,1) перемещает эту коробку немного вниз, чтобы легенда не помещалась поверх других художников.

OBS: используйте это решение ПОСЛЕ того, как вы используете fig.set_size_inches() и ДО того, как вы используете fig.tight_layout()

3 голосов
/ 12 июня 2018

Пока я немного опаздываю к игре, я дам здесь другое решение, так как это по-прежнему одна из первых ссылок, которая появляется в Google.Используя matplotlib 2.2.2, этого можно добиться с помощью функции gridspec.В приведенном ниже примере цель состоит в том, чтобы расположить четыре вспомогательных участка в формате 2x2 с легендой, показанной внизу.Внизу создается ось 'faux', чтобы разместить легенду в фиксированном месте.Затем ось «faux» отключается, поэтому отображается только легенда.Результат: https://i.stack.imgur.com/5LUWM.png.

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

#Gridspec demo
fig = plt.figure()
fig.set_size_inches(8,9)
fig.set_dpi(100)

rows   = 17 #the larger the number here, the smaller the spacing around the legend
start1 = 0
end1   = int((rows-1)/2)
start2 = end1
end2   = int(rows-1)

gspec = gridspec.GridSpec(ncols=4, nrows=rows)

axes = []
axes.append(fig.add_subplot(gspec[start1:end1,0:2]))
axes.append(fig.add_subplot(gspec[start2:end2,0:2]))
axes.append(fig.add_subplot(gspec[start1:end1,2:4]))
axes.append(fig.add_subplot(gspec[start2:end2,2:4]))
axes.append(fig.add_subplot(gspec[end2,0:4]))

line, = axes[0].plot([0,1],[0,1],'b')           #add some data
axes[-1].legend((line,),('Test',),loc='center') #create legend on bottommost axis
axes[-1].set_axis_off()                         #don't show bottommost axis

fig.tight_layout()
plt.show()
0 голосов
/ 02 мая 2019

, если вы используете вспомогательные участки с гистограммами, с разным цветом для каждой гистограммы.может быть быстрее создать артефакты самостоятельно, используя mpatches

Допустим, у вас есть четыре бара с разными цветами: r m c k Вы можете установить легенду следующим образом

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
labels = ['Red Bar', 'Magenta Bar', 'Cyan Bar', 'Black Bar']


#####################################
# insert code for the subplots here #
#####################################


# now, create an artist for each color
red_patch = mpatches.Patch(facecolor='r', edgecolor='#000000') #this will create a red bar with black borders, you can leave out edgecolor if you do not want the borders
black_patch = mpatches.Patch(facecolor='k', edgecolor='#000000')
magenta_patch = mpatches.Patch(facecolor='m', edgecolor='#000000')
cyan_patch = mpatches.Patch(facecolor='c', edgecolor='#000000')
fig.legend(handles = [red_patch, magenta_patch, cyan_patch, black_patch],labels=labels,
       loc="center right", 
       borderaxespad=0.1)
plt.subplots_adjust(right=0.85) #adjust the subplot to the right for the legend
0 голосов
/ 07 декабря 2017

Этот ответ является дополнением к @ Evert's на позиции легенды.

Моя первая попытка решения @ Evert не удалась из-за совпадений легенды и названия подзаговора.

Фактически,Перекрытия вызваны fig.tight_layout(), который меняет расположение подзаговоров без учета условных обозначений рисунка.Однако необходимо fig.tight_layout().

Чтобы избежать дублирования, мы можем fig.tight_layout() оставить пробелы для легенды фигуры на fig.tight_layout(rect=(0,0,1,0.9)).

Описаниепараметрыight_layout () .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...