я провел несколько часов, сколы прочь на этом вчера, и сделал немного прогресса, так что я поделюсь ниже вместе с некоторыми предложениями двигаться вперед.
Во-первых, кажется, что мы можем вращать и переводить ограничительную рамку (bbox) или рамку вокруг легенды. В первом примере ниже вы можете увидеть, что может применяться transform
, хотя и требует некоторых странно больших чисел перевода после применения поворота на 90 градусов. Но на самом деле проблемы с сохранением переведенного кадра легенды в файл изображения, поэтому мне пришлось сделать снимок экрана из ноутбука IPython. Я также добавил некоторые комментарии.
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import matplotlib.transforms
fig = plt.figure()
ax = fig.add_subplot('121') #make room for second subplot, where we are actually placing the legend
ax2 = fig.add_subplot('122') #blank subplot to make space for legend
ax2.axis('off')
ax.plot([4,5,6], label = 'test')
transform = matplotlib.transforms.Affine2D(matrix=np.eye(3)) #start with the identity transform, which does nothing
transform.rotate_deg(90) #add the desired 90 degree rotation
transform.translate(410,11) #for some reason we need to play with some pretty extreme translation values to position the rotated legend
legend = ax.legend(bbox_to_anchor=[1.5,1.0])
legend.set_title('test title')
legend.get_frame().set_transform(transform) #This actually works! But, only for the frame of the legend (see below)
frame = legend.get_frame()
fig.subplots_adjust(wspace = 0.4, right = 0.9)
fig.savefig('rotate_legend_1.png',bbox_extra_artists=(legend,frame),bbox_inches='tight', dpi = 300) #even with the extra bbox parameters the legend frame is still getting clipped
Далее, я думал, что было бы разумно, чтобы исследовать get_methods()
других компонентов легенды. Вы можете сортировать эти вещи с помощью dir(legend)
и legend.__dict__
и так далее. В частности, я заметил, что вы можете сделать это: legend.get_title().set_transform(transform)
, что, по-видимому, означает, что мы можем перевести текст легенды (а не только рамку, как указано выше). Давайте посмотрим, что происходит, когда я пытался что:
название
fig2 = plt.figure()
ax = fig2.add_subplot('121')
ax2 = fig2.add_subplot('122')
ax2.axis('off')
ax.plot([4,5,6], label = 'test')
transform = matplotlib.transforms.Affine2D(matrix=np.eye(3))
transform.rotate_deg(90)
transform.translate(410,11)
legend = ax.legend(bbox_to_anchor=[1.5,1.0])
legend.set_title('test title')
legend.get_frame().set_transform(transform)
legend.get_title().set_transform(transform) #one would expect this to apply the same transformation to the title text in the legend, rotating it 90 degrees and translating it
frame = legend.get_frame()
fig2.subplots_adjust(wspace = 0.4, right = 0.9)
fig2.savefig('rotate_legend_1.png',bbox_extra_artists=(legend,frame),bbox_inches='tight', dpi = 300)
Легенда кажется, исчезли в скриншоте из записной IPython. Но, если мы посмотрим на сохраненный файл название легенды теперь в нижнем левом углу, и, кажется, игнорирует компонент вращения преобразования (почему?):
Я имел аналогичные технические трудности с такой подход:
bbox = matplotlib.transforms.Bbox([[0.,1],[1,1]])
trans_bbox = matplotlib.transforms.TransformedBbox(bbox, transform)
legend.set_bbox_to_anchor(trans_bbox)
Другие замечания и предложения:
- это может быть разумная идея копаться в различиях в поведении будет между заголовком легенды и объектами кадра - почему они оба принимают преобразования, но только кадр принимает поворот? Возможно, можно было бы подклассировать объект легенды в исходном коде и внести некоторые корректировки.
- Нам также необходимо найти решение для того, чтобы рамка с повернутой/переведенной легендой не сохранялась на выходе, даже после следующих различных предложений по SO (т. Е. Matplotlib savefig with a legend outside the plot).
Был вопрос о списке Matplotlib рассылки, и ответ был, что это не представляется возможным с текущей (2009) реализации легенды (https://www.mail-archive.com/[email protected]/msg10474.html). Я никогда не сталкивался с таким вариантом при использовании более поздних версий matplotlib, возможно, это еще не возможно. –
Спасибо Крис - я нашел ту же тему и должен был включить это в мой оригинальный пост. –