Размещение легенды (bbox_to_anchor
)
Легенда располагается внутри ограничительной рамки осей, используя аргумент loc
для plt.legend
.
Например. loc="upper right"
помещает легенду в верхнем правом углу ограничительной рамки, которая по умолчанию распространяется от (0,0)
до (1,1)
в координатах осей (или в обозначении ограничительной рамки (x0,y0, width, height)=(0,0,1,1)
).
Чтобы разместить легенду за пределами ограничивающей рамки осей, можно указать кортеж (x0,y0)
координат осей нижнего левого угла легенды.
plt.legend(loc=(1.04,0))
Однако более универсальным подходом было бы вручную указать ограничивающий прямоугольник, в который следует поместить легенду, используя аргумент bbox_to_anchor
. Можно ограничить себя предоставлением только части (x0,y0)
bbox. Это создает поле нулевого диапазона, из которого легенда будет расширяться в направлении, заданном аргументом loc
. Э.Г.
plt.legend(bbox_to_anchor=(1.04,1), loc="upper left")
размещает легенду вне осей, так что верхний левый угол легенды находится в положении (1.04,1)
в координатах осей.
Дополнительные примеры приведены ниже, где дополнительно показано взаимодействие между различными аргументами, такими как mode
и ncols
.
l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0)
l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0)
l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)
l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
mode="expand", borderaxespad=0, ncol=3)
l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right",
bbox_transform=fig.transFigure, ncol=3)
l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")
Подробности о том, как интерпретировать аргумент с четырьмя кортежами в bbox_to_anchor
, как в l4
, можно найти в этого вопроса . mode="expand"
расширяет легенду по горизонтали внутри ограничительной рамки, заданной 4-кортежем. Для вертикально развернутой легенды см. этот вопрос .
Иногда бывает полезно указать ограничивающий прямоугольник в координатах фигуры вместо координат осей. Это показано в примере l5
сверху, где аргумент bbox_transform
используется для размещения легенды в левом нижнем углу рисунка.
Постобработка
Размещение легенды вне осей часто приводит к нежелательной ситуации, когда она полностью или частично выходит за пределы рисунка.
Решения этой проблемы:
Настройка параметров подплощадки
Можно настроить параметры подзаговора таким образом, чтобы оси занимали меньше места внутри фигуры (и, таким образом, оставляли больше места для легенды), используя plt.subplots_adjust
. Например.
plt.subplots_adjust(right=0.7)
оставляет 30% пространства справа от фигуры, где можно разместить легенду.
Плотный макет
Использование plt.tight_layout
Позволяет автоматически настраивать параметры подзаговора таким образом, чтобы элементы фигуры плотно прилегали к краям фигуры. К сожалению, легенда не принимается во внимание в этом автомате, но мы можем предоставить прямоугольник, в который будет помещаться вся область сюжетов (включая метки).
plt.tight_layout(rect=[0,0,0.75,1])
Сохранение рисунка с помощью bbox_inches = "tight"
Аргумент от bbox_inches = "tight"
до plt.savefig
можно использовать для сохранения рисунка, чтобы все художники на холсте (включая легенду) помещались в сохраненную область. При необходимости размер фигуры настраивается автоматически.
plt.savefig("output.png", bbox_inches="tight")
- автоматическая настройка параметров подзаговора
В этом ответе можно найти способ автоматической настройки положения подзаголовка таким образом, чтобы легенда помещалась внутри холста без изменения размера фигуры : Создание фигуры с точным размером и без отступов (и легенда вне оси)
Сравнение рассмотренных выше случаев:
Альтернативы
Легенда о фигуре
Вместо осей можно использовать легенду к фигуре matplotlib.figure.Figure.legend
. Это стало особенно полезным для версии matplotlib> = 2.1, где не требуется специальных аргументов
fig.legend(loc=7)
для создания легенды для всех художников по разным осям фигуры.Легенда размещается с использованием аргумента loc
, аналогично тому, как она размещается внутри осей, но в отношении всей фигуры - следовательно, она будет несколько вне осей автоматически.Осталось отрегулировать вспомогательные сюжеты так, чтобы не было перекрытия между легендой и осями.Здесь вам поможет пункт «Настройка параметров подзаговора» сверху.Пример:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,2*np.pi)
colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"]
fig, axes = plt.subplots(ncols=2)
for i in range(4):
axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i))
fig.legend(loc=7)
fig.tight_layout()
fig.subplots_adjust(right=0.75)
plt.show()
Легенда внутри выделенных осей подплощадок
Альтернативой использованию bbox_to_anchor
будетразместить легенду по осям отдельных сюжетов (lax
).Поскольку вспомогательный сюжет должен быть меньше, чем сюжет, мы можем использовать gridspec_kw={"width_ratios":[4,1]}
при создании осей.Мы можем скрыть оси lax.axis("off")
, но по-прежнему помещать легенду. Дескрипторы и метки легенды необходимо получить из реального сюжета через h,l = ax.get_legend_handles_labels()
, а затем их можно добавить к легенде в подпункте lax
, lax.legend(h,l)
,Полный пример приведен ниже.
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6,2
fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]})
ax.plot(x,y, label="y=sin(x)")
....
h,l = ax.get_legend_handles_labels()
lax.legend(h,l, borderaxespad=0)
lax.axis("off")
plt.tight_layout()
plt.show()
Это дает график, который визуально очень похож на график сверху:
Мы также можем использовать первые оси для размещения легенды, но используем bbox_transform
осей легенды,
ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
lax.axis("off")
В этом подходе нам не нужно получать маркеры легенды извне, но мынеобходимо указать аргумент bbox_to_anchor
.
Дополнительная литература и примечания:
- Рассмотрим руководство по легенде matplotlib с некоторыми примерами других вещей, которые вы хотите сделатьс легендами.
- Некоторые примеры кода для размещения легенд для круговых диаграмм можно найти непосредственно в ответе на этот вопрос: Python - легенда перекрывается круговой диаграммой
- The *Аргумент 1178 * может принимать числа вместо строк, что делает вызовы короче, однако они не очень интуитивно отображаются друг на друга.Вот сопоставление для справки: