Автоматическая легенда Matplotlib за пределами участка
Я пытаюсь использовать ключевое слово bbox_to_anchor()
в графике matplotlib в Python.
Вот очень простой сюжет, который я произвел:
import matplotlib.pyplot as plt
x = [1,2,3]
plt.subplot(211)
plt.plot(x, label="test1")
plt.plot([3,2,1], label="test2")
plt.legend(bbox_to_anchor=(0, -0.15, 1, 0), loc=2, ncol=2, mode="expand", borderaxespad=0)
plt.show()
Он основан на примере здесь:
http://matplotlib.org/users/legend_guide.html#plotting-guide-legend
Я пытаюсь автоматически разместить легенду вне графика с помощью bbox_to_anchor()
. В этом примере bbox_to_anchor()
содержит 4 аргумента.
В этом конкретном примере (выше) легенда помещается ниже графика, поэтому число -0.15 нужно вводить вручную каждый раз при изменении графика (размер шрифта, название оси удаляется и т.д.).
Можно ли автоматически вычислить эти 4 числа для следующих сценариев?:
- легенда ниже сюжета
- легенда выше сюжета
- легенда справа от сюжета
Если нет, возможно ли сделать хорошие догадки об этих числах в Python?
Кроме того, в приведенном выше примере кода я установил последние 2 числа в bbox_to_anchor()
равными 1 и 0, так как я не понимаю, что это такое и как они работают. Что означают последние 2 числа в bbox_to_anchor()
?
Ответы
Ответ 1
EDIT:
Я ВЫСОКО РЕКОМЕНДУЕТ ИСПОЛЬЗОВАТЬ ОТВЕТ ОТ ВАРИАНТА ОТОБРАЖЕНИЯ:
Как вывести легенду из сюжета
Это легче понять:
import matplotlib.pyplot as plt
x = [1,2,3]
plt.subplot(211)
plt.plot(x, label="test1")
plt.plot([3,2,1], label="test2")
plt.legend(bbox_to_anchor=(0, 1), loc='upper left', ncol=1)
plt.show()
теперь играем с координатами (x, y). Для loc
вы можете использовать:
valid locations are:
right
center left
upper right
lower right
best
center
lower left
center right
upper left
upper center
lower center
Ответ 2
Аргумент bbox_to_anchor находится в координатах осей. matplotlib использует различные системы координат для облегчения размещения объектов на экране. Когда речь идет о позиционировании легенд, критические системы координат для решения координат - это координаты осей, координаты фигур и координаты отображения (в пикселях), как показано ниже:
системы координат matplotlib
Как упоминалось ранее, bbox_to_anchor находится в координатах Axes и не требует всех 4 аргументов кортежа для прямоугольника. Вы можете просто дать ему двухпараметрический кортеж, содержащий (xpos, ypos) в координатах Axes. Аргумент loc в этом случае будет определять опорную точку для легенды. Таким образом, чтобы привязать легенду к внешнему праву осей и выровнять ее с верхним краем, вы должны будете сделать следующее:
lgd = plt.legend(bbox_to_anchor=(1.01, 1), loc='upper left')
Это, однако, не изменяет оси по отношению к фигуре, и это, скорее всего, позиционирует легенду на холсте рисунка. Чтобы автоматически переместить холст фигуры для выравнивания с осями и легендой, я использовал следующий алгоритм.
Сначала нарисуйте легенду на холсте, чтобы присвоить ей реальные пиксельные координаты:
plt.gcf().canvas.draw()
Затем определите преобразование для перехода от координат пикселя к координатам рисунка:
invFigure = plt.gcf().transFigure.inverted()
Далее, получите экстенты легенды в пикселях и преобразуйте их в координаты рисунка. Вытащите самый дальний размер в направлении x, так как это направление холста, которое нам нужно настроить:
lgd_pos = lgd.get_window_extent()
lgd_coord = invFigure.transform(lgd_pos)
lgd_xmax = lgd_coord[1, 0]
Сделайте то же самое для осей:
ax_pos = plt.gca().get_window_extent()
ax_coord = invFigure.transform(ax_pos)
ax_xmax = ax_coord[1, 0]
Наконец, отрегулируйте холст фигуры с помощью tight_layout для пропорции осей, которые должны переместиться, чтобы позволить помещению легенды в пределах холста:
shift = 1 - (lgd_xmax - ax_xmax)
plt.gcf().tight_layout(rect=(0, 0, shift, 1))
Обратите внимание, что аргумент rect для tight_layout находится в координатах рисунка и определяет нижний левый и верхний правый углы прямоугольника, содержащего границы узкой оси, которые не содержат легенды. Таким образом, простой вызов tight_layout эквивалентен установке прямых границ (0, 0, 1, 1).