#python #matplotlib
#python #matplotlib
Вопрос:
У меня есть несколько графиков с большим количеством информации и строк, поэтому иногда я склонен помещать легенду за пределы самого графика using bbox_to_anchor
. Я также предпочитаю иметь заголовок сюжета, но в этом случае он будет позиционно совпадать с легендой. Приведенный ниже пример является лишь иллюстрацией проблемы.
import numpy as np
import matplotlib.pyplot as plt
t = np.arange(0.0, 2.0, 0.01)
s = 1 np.sin(2 * np.pi * t)
r = 1 np.sin(4 * np.pi * t)
q = 1 np.sin(6 * np.pi * t)
fig, ax = plt.subplots()
ax.plot(t, s, label='S')
ax.plot(t, r, label='R')
ax.plot(t, q, label='Q')
leg = ax.legend(loc=3, ncol=3, bbox_to_anchor=(.0, 1.02, 1., .102), borderaxespad=0., mode='expand')
ax.set_title('SIMPLE PLOT', y=1.1)
plt.show()
Чтобы избежать этого, я устанавливаю какое-то значение y (например, y=1.1
). Я хотел бы автоматизировать этот процесс, потому что я продолжаю обновлять один и тот же график новыми данными, поэтому размер легенды увеличивается, и мне нужно соответствующим образом отрегулировать положение заголовка.
- Есть ли способ автоматизировать этот процесс?
- Есть ли в Python функция, способная считывать высоту легенды, чтобы это можно было использовать для настройки положения заголовка?
Ответ №1:
Высота легенды определяется во время рисования. Вы можете получить это после рисования фигуры через legend.get_window_extent()
. Результирующая ограничивающая рамка указана в единицах пикселей. Для того, чтобы найти смещение заголовка, вам нужно будет вычесть верхний предел легенды из верхнего предела осей. Итак, вам также нужно получить положение осей в пикселях.
Заголовок может быть смещен либо в координатах рисунка ( y=1.1
), либо в точках ( pad=20
). Я бы предложил использовать точки здесь, чтобы сделать это независимым от размера осей. Таким образом, вы можете вычислить разницу в верхних позициях, преобразовать из пикселей в точки (т. Е. distance [pixels] * ppi / dpi
) и добавить некоторое постоянное смещение в точках (потому что обычно вы не хотели бы, чтобы заголовок располагался точно на границе легенды). Затем используйте это число как pad
.
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(constrained_layout=True)
ax.plot([1,2,3], np.random.rand(3,5), label='Label')
leg = ax.legend(loc="lower center", ncol=3, bbox_to_anchor=(.0, 1.02, 1., 1.02),
borderaxespad=0, mode='expand')
fig.canvas.draw()
leg_box = leg.get_window_extent()
ax_box = ax.get_position().transformed(fig.transFigure)
pad = (leg_box.y1 - ax_box.y1)*72./fig.dpi 6
ax.set_title('SIMPLE PLOT', pad=pad)
plt.show()
Обратите внимание, что здесь я также использовал constrained_layout
, чтобы заголовок не обрезался границами рисунка.
Комментарии:
1. Спасибо, @ImportanceOfBeingErnest — это было на самом деле то, что я имел в виду!