Ответ 1
Сначала объясним вывод из вопроса: при использовании 2-кортежной нотации для bbox_to_anchor
создается ограничивающий прямоугольник без растягивания. mode="expand"
будет расширять легенду горизонтально в эту ограничительную рамку, которая имеет нулевую длину, эффективно уменьшая ее до нулевого размера.
Проблема заключается в том, что mode="expand"
расширяет легенду только по горизонтали.
Из документация:
mode
: { "expand", None}
Если для режима установлено значение "expand", легенда будет горизонтально расширена, чтобы заполнить область осей (или bbox_to_anchor, если определяет размер легенд).
Для решения вам нужно глубоко вникать в легендарные внутренние элементы. Во-первых, вам нужно установить привязку bbox-to-anchor с 4-кортежем, указав также ширину и высоту bbox, bbox_to_anchor=(x0,y0,width,height)
, где все числа находятся в координатах с координатами координат. Затем вам нужно рассчитать высоту легенды _legend_box
. Поскольку есть определенное дополнение, вам нужно вычесть это заполнение из высоты ограничивающего прямоугольника. Чтобы рассчитать заполнение, необходимо знать текущий шрифт легенды. Все это должно произойти после последнего изменения положения осей.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2*np.pi, 100)
data = [np.sin(x * np.pi/float(el)) for el in range(1, 5)]
fig, ax = plt.subplots(1)
for key, el in enumerate(data):
ax.plot(x, el, label=str(key))
# legend:
leg = ax.legend(bbox_to_anchor=(1.04,0.0,0.2,1), loc="lower left",
borderaxespad=0, mode='expand')
plt.tight_layout(rect=[0,0,0.8,1])
# do this after calling tight layout or changing axes positions in any way:
fontsize = fig.canvas.get_renderer().points_to_pixels(leg._fontsize)
pad = 2 * (leg.borderaxespad + leg.borderpad) * fontsize
leg._legend_box.set_height(leg.get_bbox_to_anchor().height-pad)
plt.show()