Mam serię 20 wykresów (nie podplotów), które należy wykonać w jednym rysunku. Chcę, żeby legenda była poza pudełkiem. Jednocześnie nie chcę zmieniać osi, ponieważ zmniejsza się rozmiar figury. Prosimy o pomoc w przypadku następujących pytań:
- Chcę zachować pole legendy poza obszarem fabuły. (Chcę, aby legenda była na zewnątrz po prawej stronie obszaru fabuły).
- Czy w każdym razie zmniejszam rozmiar czcionki tekstu w polu legendy, aby rozmiar pola legendy był niewielki.
python
matplotlib
legend
pottigopi
źródło
źródło
https://stackoverflow.com/a/43439132/52074
. i robi to za pomocą dwóch linii kodu! pozytywna odpowiedź +1200 jest również dobra, ale uważam, że jest mniej ogólna.Odpowiedzi:
Możesz zmniejszyć tekst legendy, tworząc właściwości czcionki:
źródło
plot1
w tej odpowiedzi?legend
w tej odpowiedzi?plt.legend(fontsize='small')
Istnieje wiele sposobów robienia tego, co chcesz. Aby dodać do tego, co już powiedzieli @inalis i @Navi, możesz użyć
bbox_to_anchor
argumentu słowa kluczowego, aby umieścić legendę częściowo poza osiami i / lub zmniejszyć rozmiar czcionki.Zanim zastanowisz się nad zmniejszeniem rozmiaru czcionki (co może uczynić rzeczy okropnie trudnymi do odczytania), spróbuj pobawić się legendą w różnych miejscach:
Zacznijmy od ogólnego przykładu:
Jeśli zrobimy to samo, ale użyjemy
bbox_to_anchor
argumentu słowa kluczowego, możemy przesunąć legendę nieco poza granice osi:Podobnie możesz ustawić legendę bardziej poziomo i / lub umieścić ją na górze figury (włączam również zaokrąglone rogi i prosty cień):
Alternatywnie możesz zmniejszyć szerokość bieżącego wykresu i umieścić legendę całkowicie poza osią figury (uwaga: jeśli używasz tight_layout () , to pomiń ax.set_position ():
W podobny sposób możesz zmniejszyć fabułę w pionie i umieścić na dole poziomą legendę:
Spojrzeć w przewodniku matplotlib legendy . Możesz także rzucić okiem
plt.figlegend()
.źródło
bbox_to_anchor
jest krotką 4 pływaków (x, y, szerokość, wysokość skrzynki) lub krotką 2 pływaków (x, y) w znormalizowanych osiach współrzędne. ”legend = ax.legend()
I późniejfig.savefig(bbox_extra_artists=(legend,))
Umieszczanie legendy (
bbox_to_anchor
)Legenda jest umieszczana wewnątrz obwiedni osi za pomocą
loc
argumentu doplt.legend
.Np.
loc="upper right"
Umieszcza legendę w prawym górnym rogu ramki ograniczającej, która domyślnie rozciąga się od(0,0)
do(1,1)
współrzędnych osi (lub w notacji ramki ograniczającej(x0,y0, width, height)=(0,0,1,1)
).Aby umieścić legendę poza obwiednią osi, można określić krotkę
(x0,y0)
współrzędnych osi lewego dolnego rogu legendy.Jednak bardziej uniwersalnym podejściem byłoby ręczne określenie ramki granicznej, w której legenda powinna zostać umieszczona, za pomocą
bbox_to_anchor
argumentu. Można ograniczyć się do dostarczania tylko(x0,y0)
części skrzynki. Tworzy to pole zerowego zakresu, z którego legenda będzie się rozwijać w kierunku podanym przezloc
argument. Na przykładumieszcza legendę poza osiami, tak aby lewy górny róg legendy był ustawiony
(1.04,1)
we współrzędnych osi.Dalsze przykłady podano poniżej, gdzie dodatkowo pokazano wzajemne oddziaływanie różnych argumentów, takich jak
mode
incols
.Szczegółowe informacje na temat interpretacji argumentu 4-krotnego
bbox_to_anchor
, podobnie jak wl4
, można znaleźć w tym pytaniu .mode="expand"
Rozszerza legendę poziomo wewnątrz obwiedni określonej przez 4-krotnego. W przypadku legendy rozwiniętej pionowo zobacz to pytanie .Czasami może być przydatne określenie ramki granicznej we współrzędnych figury zamiast we współrzędnych osi. Jest to pokazane w
l5
powyższym przykładzie , w którymbbox_transform
argument jest używany do umieszczenia legendy w lewym dolnym rogu figury.Przetwarzanie końcowe
Umieszczenie legendy poza osiami często prowadzi do niepożądanej sytuacji, że jest ona całkowicie lub częściowo poza płótnem postaci.
Rozwiązaniami tego problemu są:
Dostosuj parametry podplotu
Można tak dostosować parametry podplotu, aby osie zajmowały mniej miejsca wewnątrz figury (a tym samym pozostawiły więcej miejsca legendzie) za pomocą
plt.subplots_adjust
. Na przykładpozostawia 30% miejsca po prawej stronie figury, gdzie można umieścić legendę.
Ciasny układ
Używanie
plt.tight_layout
Umożliwia automatyczne dostosowanie parametrów wykresu podrzędnego, tak aby elementy na figurze ściśle przylegały do krawędzi figury. Niestety, legenda nie jest brana pod uwagę w tym automatyzmie, ale możemy dostarczyć prostokątne pudełko, w które zmieści się cały obszar podplotów (w tym etykiety).Zapisywanie figury za pomocą
bbox_inches = "tight"
Argumentu,
bbox_inches = "tight"
zaplt.savefig
pomocą którego można zapisać figurę, tak aby wszyscy artyści na płótnie (w tym legenda) byli dopasowani do zapisanego obszaru. W razie potrzeby wielkość figury jest automatycznie dostosowywana.Sposób na automatyczne dopasowanie położenia wykresu podrzędnego tak, aby legenda mieściła się w obszarze roboczym bez zmiany rozmiaru figury, można znaleźć w tej odpowiedzi: Tworzenie figury z dokładnym rozmiarem i bez dopełnienia (i legenda poza osiami)
Porównanie przypadków omówionych powyżej:
Alternatywy
Postać legenda
One mogą wykorzystywać legendę do figury zamiast z osi
matplotlib.figure.Figure.legend
. Stało się to szczególnie przydatne w wersji matplotlib> = 2.1, gdzie nie są potrzebne żadne specjalne argumentystworzyć legendę dla wszystkich artystów w różnych osiach figury. Legenda jest umieszczana za pomocą
loc
argumentu, podobnie jak jest umieszczona w osiach, ale w odniesieniu do całej figury - stąd będzie nieco automatycznie poza osiami. Pozostaje tak wyregulować wykresy podrzędne, aby legenda i osie nie zachodziły na siebie. W tym przypadku pomocny będzie punkt „Dostosuj parametry podplotu” z góry. Przykład:Legenda w dedykowanych osiach podplotu
Alternatywą dla użycia
bbox_to_anchor
byłoby umieszczenie legendy w dedykowanych osiach podplotu (lax
). Ponieważ podplot legendy powinien być mniejszy niż wykres, możemy go wykorzystaćgridspec_kw={"width_ratios":[4,1]}
przy tworzeniu osi. Możemy ukryć osielax.axis("off")
ale nadal umieścić legendę w. Uchwyty legenda i etykiety muszą uzyskać od rzeczywistej działce pośrednictwemh,l = ax.get_legend_handles_labels()
, a następnie może być dostarczony do legendy wlax
poletko,lax.legend(h,l)
. Pełny przykład znajduje się poniżej.To tworzy wykres, który jest wizualnie bardzo podobny do wykresu z góry:
Możemy również użyć pierwszych osi do umieszczenia legendy, ale użyj
bbox_transform
osi legendy,W tym podejściu nie musimy uzyskiwać uchwytów legendy zewnętrznie, ale musimy podać
bbox_to_anchor
argument.Dalsza lektura i notatki:
loc
Argument może wziąć numery zamiast strun, które sprawiają, że rozmowy krótszy, jednak nie są one bardzo intuicyjnie odwzorowywane na siebie. Oto mapowanie w celach informacyjnych:źródło
fig.tight_layout
. Jeśli używaszplt.subplots
do tworzenia osi, po prostu daj mu coś w rodzajugridspec_kw={'height_ratios': [100, 1]}
(lub width_ratios), aby osie legendy były małe ... Następniefig.tight_layout()
rozszerzy ją, aby pasowała. Przynajmniej dla Matplotlib 3.0.3.Po prostu zadzwoń
legend()
po takimplot()
połączeniu:Wyniki wyglądałyby mniej więcej tak:
źródło
Aby umieścić legendę poza obszarem fabuły, użyj
loc
ibbox_to_anchor
słów kluczowychlegend()
. Na przykład poniższy kod umieści legendę po prawej stronie obszaru wydruku:Aby uzyskać więcej informacji, zobacz przewodnik legendy
źródło
plt.tight_layout()
?Krótka odpowiedź: możesz użyć
bbox_to_anchor
+bbox_extra_artists
+bbox_inches='tight'
.Dłuższa odpowiedź: można użyć
bbox_to_anchor
do ręcznego określenia położenia pola legendy, jak wskazały inne osoby w odpowiedziach.Jednak zwykłym problemem jest przycięcie pola legendy, np .:
Aby zapobiec przycięciu pola legendy, po zapisaniu figury możesz użyć parametrów
bbox_extra_artists
ibbox_inches
poprosićsavefig
o dołączenie przyciętych elementów do zapisanego obrazu:fig.savefig('image_output.png', bbox_extra_artists=(lgd,), bbox_inches='tight')
Przykład (zmieniłem tylko ostatni wiersz, aby dodać 2 parametry
fig.savefig()
):Chciałbym, aby matplotlib natywnie umożliwiał zewnętrzną lokalizację skrzynki z legendami, ponieważ Matlab :
źródło
bbox_inches='tight'
działa dla mnie idealnie, nawet bez bbox_extra_artistOprócz wszystkich doskonałych odpowiedzi tutaj, nowsze wersje
matplotlib
ipylab
mogą automatycznie określać, gdzie umieścić legendę bez ingerencji w fabuły , jeśli to możliwe.To automatycznie umieści legendę z dala od danych, jeśli to możliwe!
Jeśli jednak nie ma miejsca na umieszczenie legendy bez nakładania się danych, warto wypróbować jedną z pozostałych odpowiedzi; użycie
loc="best"
nigdy nie wystawi legendy poza fabułę.źródło
Krótka odpowiedź : przywołaj legendę do przeciągania i interaktywnie przenieś ją w dowolne miejsce:
Długa odpowiedź : jeśli wolisz umieszczać legendę interaktywnie / ręcznie niż programowo, możesz przełączyć tryb przeciągania legendy, aby można było przeciągnąć ją w dowolne miejsce. Sprawdź poniższy przykład:
źródło
Nie do końca to, o co prosiłeś, ale znalazłem alternatywę dla tego samego problemu. Uczyń legendę półprzezroczystą, tak jak to:
Zrób to z:
źródło
Jak już wspomniano, można również umieścić legendę na fabule lub nieco ją odsunąć do krawędzi. Oto przykład użycia interfejsu API programu Plotly Python , wykonanego za pomocą notatnika IPython . Jestem w zespole.
Na początek musisz zainstalować niezbędne pakiety:
Następnie zainstaluj Plotly:
Spowoduje to utworzenie wykresu i pozwoli zachować legendę w samym wykresie. Domyślną legendą, jeśli nie jest ustawiona, jest umieszczenie jej na wykresie, jak pokazano tutaj.
W celu alternatywnego umieszczenia możesz ściśle wyrównać krawędź wykresu i obramowanie legendy oraz usunąć linie obramowania w celu ściślejszego dopasowania.
Możesz przenieść i zmienić styl legendy i wykresu za pomocą kodu lub GUI. Aby przesunąć legendę, masz następujące opcje, aby umieścić legendę na wykresie, przypisując wartości xiy <= 1. Np .:
{"x" : 0,"y" : 0}
-- Na dole po lewej{"x" : 1, "y" : 0}
-- Prawy dolny{"x" : 1, "y" : 1}
-- W prawym górnym rogu{"x" : 0, "y" : 1}
-- U góry z lewej{"x" :.5, "y" : 0}
- Dolny środek{"x": .5, "y" : 1}
- Top CenterW takim przypadku wybieramy prawy górny róg
legendstyle = {"x" : 1, "y" : 1}
, również opisany w dokumentacji :źródło
Coś w tym stylu działało dla mnie. Począwszy od odrobiny kodu pobranego od Joe, ta metoda modyfikuje szerokość okna, aby automatycznie dopasować legendę po prawej stronie figury.
źródło
mgr.window.wm_geometry(...)
zmgr.window.setFixedWidth(winWidthNew)
.fig.set_size_inches(...)
dba o potrzebny rozmiar.Warto odświeżyć to pytanie, ponieważ nowsze wersje Matplotlib znacznie ułatwiły umieszczenie legendy poza fabułą. Ten przykład stworzyłem w wersji Matplotlib
3.1.1
.Użytkownicy mogą przekazać 2-krotną współrzędną do
loc
parametru, aby umieścić legendę w dowolnym miejscu w obwiedni. Jedyne, co musisz zrobić, to uruchomić programplt.tight_layout()
Matplotlib, aby ponownie obliczyć wymiary działki, aby legenda była widoczna:Prowadzi to do następującego wątku:
Bibliografia:
źródło
Możesz także spróbować
figlegend
. Możliwe jest utworzenie legendy niezależnej od dowolnego obiektu Axes. Konieczne może być jednak utworzenie ścieżek „fikcyjnych”, aby upewnić się, że formatowanie obiektów zostanie poprawnie przekazane.źródło
Oto przykład z samouczka matplotlib znalezionego tutaj . Jest to jeden z prostszych przykładów, ale dodałem przezroczystość do legendy i dodałem plt.show (), abyś mógł wkleić to do interaktywnej powłoki i uzyskać wynik:
źródło
Rozwiązaniem, które działało dla mnie, gdy miałem wielką legendę, było użycie dodatkowego pustego układu obrazu. W poniższym przykładzie wykonałem 4 rzędy, a na dole kreślę obraz z przesunięciem dla legendy (bbox_to_anchor) u góry, który nie jest wycinany.
źródło
Oto inne rozwiązanie, podobne do dodawania
bbox_extra_artists
ibbox_inches
, w którym nie musisz mieć dodatkowych artystów w zasięgusavefig
rozmowy. Wymyśliłem to, ponieważ generuję większość moich wykresów w funkcjach.Zamiast dodawać wszystkie swoje dodatki do obwiedni, gdy chcesz je wypisać, możesz dodać je z wyprzedzeniem do
Figure
artystów. Używając czegoś podobnego do powyższej odpowiedzi Francka Dernoncourta :Oto wygenerowany wykres.
źródło
nie wiem, czy już rozwiązałeś problem ... prawdopodobnie tak, ale ... po prostu użyłem ciągu „na zewnątrz” dla lokalizacji, jak w Matlabie. Zaimportowałem pylab z Matplotlib. zobacz kod w następujący sposób:
Kliknij, aby zobaczyć fabułę
źródło