2015-05-23 14 views
12

Próbuję użyć słowa kluczowego bbox_to_anchor() na wykresie matplotlib w Pythonie.Automatyczna legenda Matplotlib poza polem

Oto bardzo prosty Działka że wyprodukowali:

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() 

Jest on oparty na przykład tutaj: http://matplotlib.org/users/legend_guide.html#plotting-guide-legend

Próbuję automatycznie umieścić legendę poza działce przy użyciu bbox_to_anchor(). W tym przykładzie bbox_to_anchor() zawiera 4 argumenty.

W tym konkretnym przykładzie (powyżej) legenda jest umieszczona poniżej wykresu, więc numer -0.15 należy wprowadzić ręcznie za każdym razem, gdy zostanie zmieniony wykres (rozmiar czcionki, tytuł osi usunięty itp.). Czy jest możliwe automatyczne obliczenie tych 4 liczb dla następujących scenariuszy?:

  1. legenda poniżej działki
  2. legendy powyżej działki
  3. legenda do prawej działki

jeśli nie, to jest możliwe do naprawienia domysły na temat tych liczb, w Pythonie?

Również w powyższym przykładowym kodzie ustawiłem 2 ostatnie liczby w bbox_to_anchor() na 1 i 0, ponieważ nie rozumiem, czym one są i jak działają. Co oznaczają ostatnie 2 cyfry w numerze bbox_to_anchor()?

Odpowiedz

17

EDIT:

mogę polecić korzystanie odpowiedzi z ImportanceOfBeingErnest: How to put the legend out of the plot

ten jest łatwiejszy do zrozumienia:

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() 

teraz grać z do współrzędnych (x, y). Dla loc można użyć:

valid locations are: 
right 
center left 
upper right 
lower right 
best 
center 
lower left 
center right 
upper left 
upper center 
lower center 
+1

Dzięki. Czy nie trzeba ustawiać ręcznie współrzędnych za każdym razem? –

+0

Etykiety dataserii są dla mnie bardzo długie. W legendzie powoduje to ich odcięcie. Czy istnieje sposób, aby tego uniknąć? –

+1

Jeśli ustawisz "lewy górny" i np. (1, 25) legenda znajduje się poza polem. Legendy powinny być krótkie i tak – Moritz

1

Argument bbox_to_anchor jest w Osie współrzędnych. matplotlib używa różnych układów współrzędnych, aby ułatwić umieszczanie obiektów na ekranie. Gdy mamy do czynienia legendą pozycjonującymi krytyczna systemów do czynienia z stanowią współrzędne osie, figura współrzędnych i współrzędne wyświetlacza (w pikselach) współrzędnych, jak pokazano poniżej:

matplotlib coordinate systems

Jak wcześniej wspomniano, bbox_to_anchor znajduje się współrzędne osi i nie wymaga wszystkich 4 argumentów krotki dla prostokąta. Możesz po prostu nadać mu dwuargumentową krotkę zawierającą (xpos, ypos) we współrzędnych osi. Argument loc w tym przypadku definiuje punkt zakotwiczenia legendy.Tak aby przypiąć legendę do zewnętrznej prawej stronie osi i wyrównany z górną krawędzią, należy wydać następujące:

lgd = plt.legend(bbox_to_anchor=(1.01, 1), loc='upper left') 

To jednak nie zmienić położenie osi w stosunku do rysunku i będzie to prawdopodobnie Stanowisko legenda off z płótna rysunku. Aby automatycznie zmienić położenie płótna rysunku w celu dopasowania do osi i legendy, użyłem następującego algorytmu.

Pierwszy współrzędne, rysować legendę na płótnie, aby go przypisać prawdziwy pikseli:

plt.gcf().canvas.draw() 

Następnie zdefiniować transformację, aby przejść od współrzędnych pikseli Rysunek współrzędne:

invFigure = plt.gcf().transFigure.inverted() 

Następnie uzyskać legenda rozciąga się w pikselach i konwertuje na współrzędne figur. Wyciągnąć najdalszy zasięg w kierunku X, ponieważ jest to kierunek płótno musimy dostosować:

lgd_pos = lgd.get_window_extent() 
lgd_coord = invFigure.transform(lgd_pos) 
lgd_xmax = lgd_coord[1, 0] 

Zrób to samo dla osi:

ax_pos = plt.gca().get_window_extent() 
ax_coord = invFigure.transform(ax_pos) 
ax_xmax = ax_coord[1, 0] 

Wreszcie dostosowania pozycji płótno za pomocą tight_layout dla proporcja osie, które muszą poruszać się w celu umożliwienia miejsce na legendzie do dopasowania do płótna:

shift = 1 - (lgd_xmax - ax_xmax) 
plt.gcf().tight_layout(rect=(0, 0, shift, 1)) 

Argument ten rect tight_layout jest na rysunku COOR dinates i definiuje dolny lewy i prawy górny narożnik prostokąta zawierający obwiednie tight_layout osi, które nie zawierają legendy. Tak więc proste wywołanie tight_layout jest równoważne ustawieniu prostokątnych granic (0, 0, 1, 1).

+0

to jest świetna odpowiedź. Jest to jedyna, której próbowałem, działa programowo. Dobra robota też to wyjaśnia; Byłoby miło mieć bardziej ogólną odpowiedź, która mogłaby się zmienić w dowolnym kierunku, gdyby legenda została umieszczona powyżej/poniżej figury, na przykład. – shapiromatron

Powiązane problemy