Spędziłem kilka godzin Zmniejszanie tego wczoraj, wykonane nieco postępu więc będę dzielić się poniżej wraz z kilka sugestii posuwa się naprzód.
Po pierwsze, wydaje się, że możemy z pewnością obrócić i przetłumaczyć ramkę ograniczającą (bbox) lub ramkę wokół legendy. W pierwszym przykładzie poniżej można zobaczyć, że można zastosować transform
, aczkolwiek po zastosowaniu obrotu o 90 stopni wymagane są niektóre dziwnie duże liczby tłumaczeń. Ale faktycznie istnieją problemy z zapisaniem przetłumaczonej ramki legendy na plik obrazu, więc musiałem wykonać zrzut ekranu z notatnika IPython. Dodałem także kilka komentarzy.
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
Następny, myślałem, że będzie mądry, żeby zbadać get_methods()
innych elementów legendy. Możesz sortować te rzeczy z dir(legend)
i legend.__dict__
i tak dalej. W szczególności zauważyłem, że możesz to zrobić: legend.get_title().set_transform(transform)
, co mogłoby sugerować, że możemy przetłumaczyć tekst legendy (a nie tylko ramkę jak wyżej). Zobaczmy, co się dzieje, gdy próbowałem to:
tytuł
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)
legenda wydaje się, że zniknął na zrzucie z notebooka ipython. Ale jeśli spojrzymy na zapisanego pliku tytuł legendy jest w lewym dolnym rogu i wydaje się być ignorowane komponent obrotu przekształcenia (dlaczego?):
miałem podobne problemy techniczne z ten rodzaj podejścia:
bbox = matplotlib.transforms.Bbox([[0.,1],[1,1]])
trans_bbox = matplotlib.transforms.TransformedBbox(bbox, transform)
legend.set_bbox_to_anchor(trans_bbox)
Inne uwagi i sugestie:
- to może być sensowny pomysł, aby zagłębić się różnic w zachowaniu się pomiędzy tytułem legendy a obiektami ramek - dlaczego obie akceptują transformacje, ale tylko ramka akceptuje obrót? Być może możliwe byłoby podklasy obiektu legendy w kodzie źródłowym i dokonać pewnych korekt.
- Musimy również znaleźć rozwiązanie, w którym obrócona/przetłumaczona ramka legendy nie jest zapisywana na wyjściu, nawet po wykonaniu różnych powiązanych sugestii na temat SO (tj. Matplotlib savefig with a legend outside the plot).
Było pytanie na liście matplotlib korespondencji, a odpowiedź brzmiała, że nie jest to możliwe z obecnym (2009) wdrożenie legendy (https://www.mail-archive.com/[email protected]/msg10474.html). Nigdy nie spotkałem się z taką opcją podczas korzystania z nowszych wersji matplotlib, może to nadal nie jest możliwe. –
Dzięki Chris - Znalazłem ten sam wątek i powinienem uwzględnić to w moim oryginalnym wpisie. –