Як викласти легенду з сюжету


987

У мене є серія з 20 сюжетів (а не субплотів), які потрібно зробити однією фігурою. Я хочу, щоб легенда була поза коробкою. У той же час я не хочу змінювати осі, оскільки розмір фігури зменшується. Будь ласка, допоможіть мені в наступних запитах:

  1. Я хочу тримати поле легенди поза межами ділянки. (Я хочу, щоб легенда була зовні на правій частині ділянки).
  2. Чи все-таки я зменшую розмір шрифту тексту всередині поля «Легенда», щоб розмір поля «Легенда» був невеликим.

14
Для нових версій matplotlib ця відповідь показує, як встановити matplotlib для автоматичного визначення місця, куди слід ставити легенду, не втручаючись у сюжети .
dotancohen

2
У мене було те саме питання, і я знайшов цей чудовий приклад, який працював на мене "поза коробкою": matplotlib.org/1.3.1/users/legend_guide.html
robodasha

1
Ця відповідь має більшу глибину https://stackoverflow.com/a/43439132/52074. і робить це з двома рядками коду! +1200 відповіла відповідь також хороша, але я виявив, що вона менш загальна.
Тревор Бойд Сміт

2
@dotancohen "автоматично визначає, куди поставити легенду, не втручаючись у сюжети" У певних випадках, коли сюжет має багато кривих, це, на жаль, неможливо. У цих випадках користувач може захотіти розмістити легенду вручну та й справді викласти її за межі ділянки. У мене зараз є труднощі з таким сюжетом.
Алі

btw, список варіантів локації: кращий; праворуч; лівий верхній; внизу зліва; праворуч внизу; правильно; центр зліва; праворуч по центру; нижній центр; верхній центр; центр;
Z-Y00

Відповіді:


57

Ви можете зменшити текст легенди, створивши властивості шрифту:

from matplotlib.font_manager import FontProperties

fontP = FontProperties()
fontP.set_size('small')
legend([plot1], "title", prop=fontP) 
# or add prop=fontP to whatever legend() call you already have

50
що plot1в цій відповіді?
Пол H

41
що legendв цій відповіді?
Річард

28
Це відповідає на другорядну частину питання, але не на первинну (ту, що має назву).
Mateen Ulhaq

8
Також правильний спосіб зробити цеplt.legend(fontsize='small')
Mateen Ulhaq

41
Ця відповідь жахлива і забезпечує дуже мало контексту!
Текіль

1794

Існує ряд способів зробити те, що ви хочете. Щоб додати те, що вже говорили @inalis та @Navi, ви можете використовувати bbox_to_anchorаргумент ключового слова, щоб розмістити легенду частково поза осями та / або зменшити розмір шрифту.

Перш ніж задуматися про зменшення розміру шрифту (що може зробити речі важко важкими для читання), спробуйте пограти, розмістивши легенду в різних місцях:

Отже, почнемо із загального прикладу:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$' % i)

ax.legend()

plt.show()

alt текст

Якщо ми робимо те саме, але використовуючи bbox_to_anchorаргумент ключового слова, ми можемо зсунути легенду трохи за межі осей:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$' % i)

ax.legend(bbox_to_anchor=(1.1, 1.05))

plt.show()

alt текст

Аналогічно, ви можете зробити легенду більш горизонтальною та / або поставити її у верхній частині фігури (я також повертаю закруглені кути та просту тінь для краплі):

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)

ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.05),
          ncol=3, fancybox=True, shadow=True)
plt.show()

alt текст

Крім того, ви можете зменшити ширину поточної ділянки і поставити легенду повністю за межами осі фігури (зверніть увагу: якщо ви використовуєте " тісно_лаут" () , тоді не залишайте ax.set_position ():

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$'%i)

# Shrink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])

# Put a legend to the right of the current axis
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

plt.show()

alt текст

І аналогічним чином ви можете стиснути сюжет вертикально, а внизу поставити горизонтальну легенду:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)

# Shrink current axis's height by 10% on the bottom
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])

# Put a legend below current axis
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
          fancybox=True, shadow=True, ncol=5)

plt.show()

alt текст

Погляньте на посібник з легенди про matplotlib . Ви також можете поглянути plt.figlegend().


10
Якщо у кого-небудь є проблеми з цим, зауважте, що зв’язати тіло_layout () буде проблема!
Метью Г.

4
чудова відповідь! правильне посилання на документ - matplotlib.org/users/legend_guide.html#legend-location
meduz

4
як повнота, можна сказати, що в цілому (підсумовується з doc) " bbox_to_anchorє кортеж із 4 поплавків (x, y, ширина, висота коробки), або кортеж з 2 поплавків (x, y) у нормалізованих осях координати. "
медуз

5
Я мушу визнати, що це, мабуть, моя найбільш відвідувана відповідь ТА колись. Я просто не можу не повертатися до неї знову і знову, тому що немає можливості розумній людині запам'ятати цю логіку, не шукаючи її тут.
КТ.

9
Зауважте, що якщо ви хочете зберегти фігуру у файл, ви, ймовірно, повинні зберігати повернутий об'єкт, тобто legend = ax.legend()пізнішеfig.savefig(bbox_extra_artists=(legend,))
coldfix

788

Розміщення легенди ( bbox_to_anchor)

У межах обмежувальної коробки осей розташована легенда, використовуючи locаргумент до plt.legend.
Наприклад, loc="upper right"розміщується легенда у верхньому правому куті обмежувальної коробки, яка за замовчуванням поширюється (0,0)на (1,1)координати осей (або в позначення рамки (x0,y0, width, height)=(0,0,1,1)).

Для розміщення легенди поза межами осі, що обмежує вікно, можна вказати кордон (x0,y0)координат осей нижнього лівого кута легенди.

plt.legend(loc=(1.04,0))

Однак більш універсальним підходом було б вручну вказати обмежувальне поле, в яке слід розмістити легенду, використовуючи bbox_to_anchorаргумент. Можна обмежити себе лише (x0,y0)частиною скриньки. Це створює поле нульового прольоту, з якого легенда буде розширюватися у напрямку, заданому locаргументом. Напр

plt.legend (bbox_to_anchor = (1,04,1), loc = "верхній лівий")

розміщує легенду за межами осей, таким чином, щоб лівий верхній кут легенди був у положенні (1.04,1)в координатах осей.

Далі наведено подальші приклади, де додатково показано взаємозв'язок між різними аргументами, як modeі ncolsпоказано.

введіть тут опис зображення

l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0)
l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0)
l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)
l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
                mode="expand", borderaxespad=0, ncol=3)
l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right", 
                bbox_transform=fig.transFigure, ncol=3)
l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")

Деталі про те, як інтерпретувати аргумент із 4-ма кордонами bbox_to_anchor, як у l4, можна знайти у цьому запитанні . mode="expand"Розширює легенду горизонтально всередині прямокутника , заданий 4-кортежу. Для вертикально розширеної легенди дивіться це питання .

Іноді може бути корисним вказати обмежувальне поле у ​​координатах фігур замість координат осей. Це показано в прикладі l5зверху, де bbox_transformаргумент використовується для розміщення легенди в лівому нижньому куті фігури.

Подальша обробка

Розміщення легенди поза осями часто призводить до небажаної ситуації, що вона повністю або частково знаходиться поза полотном фігури.

Рішення цієї проблеми:

  • Налаштування параметрів субплоти
    Ви можете налаштувати параметри субплоти таким чином, щоб осі займали менше місця всередині фігури (і тим самим залишали більше місця для легенди), використовуючи plt.subplots_adjust. Напр

    plt.subplots_adjust(right=0.7)

    залишає 30% місця на правій частині фігури, де можна було розмістити легенду.

  • Тугий макет
    Використання plt.tight_layoutДозволяє автоматично регулювати параметри субплоти, щоб елементи на рисунку щільно прилягали до країв фігури. На жаль, легенда не враховується в цьому автоматизмі, але ми можемо поставити прямокутну коробку, в яку поміститься вся область піддосів (включаючи мітки).

    plt.tight_layout(rect=[0,0,0.75,1])
  • Збереження фігури зbbox_inches = "tight"
    Аргумент , bbox_inches = "tight"щоб plt.savefigможна використовувати , щоб зберегти фігуру таким чином, що всі художники на полотні ( в тому числі легенди) придатні в збереженої область. При необхідності розмір фігури автоматично регулюється.

    plt.savefig("output.png", bbox_inches="tight")
  • автоматичне налаштування параметрів субплоти.
    У цій відповіді можна знайти спосіб автоматичного регулювання положення субплату таким чином, щоб легенда вміщувалася всередину полотна, не змінюючи розмір фігури : Створення фігури з точним розміром та відсутністю прокладки (та легенди поза осями)

Порівняння між розглянутими вище випадками:

введіть тут опис зображення

Альтернативи

Фігура Легенда
Можна використовувати умовні позначення на фігурі замість осей, matplotlib.figure.Figure.legend. Це стало особливо корисним для версії matplotlib> = 2.1, де спеціальних аргументів не потрібно

fig.legend(loc=7) 

створити легенду для всіх художників у різних осях фігури. Легенда розміщується за допомогою locаргументу, подібно до того, як вона розміщена всередині осей, але по відношенню до всієї фігури - значить, вона буде поза осями дещо автоматично. Залишилося налаштувати субплоти так, щоб між легендою та осями не було перекриттів. Тут корисним буде пункт "Налаштування параметрів субплоти" зверху. Приклад:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,2*np.pi)
colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"]
fig, axes = plt.subplots(ncols=2)
for i in range(4):
    axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i))

fig.legend(loc=7)
fig.tight_layout()
fig.subplots_adjust(right=0.75)   
plt.show()

введіть тут опис зображення

Легенда всередині виділених осей subplot
Альтернативою використанню bbox_to_anchorможе бути розміщення легенди у її виділених осях subplot ( lax). Оскільки підводка легенди має бути меншою за графік, ми можемо використовувати gridspec_kw={"width_ratios":[4,1]}при створенні осей. Ми можемо приховати вісь , lax.axis("off")але все - таки поставити легенду. Легенда ручці і етикетки повинні отримати з реального ділянки через h,l = ax.get_legend_handles_labels(), а потім можемо бути подані в легенду в laxсюжетному, lax.legend(h,l). Повний приклад наведено нижче.

import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6,2

fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]})
ax.plot(x,y, label="y=sin(x)")
....

h,l = ax.get_legend_handles_labels()
lax.legend(h,l, borderaxespad=0)
lax.axis("off")

plt.tight_layout()
plt.show()

Це створює сюжет, який візуально дуже схожий на сюжет зверху:

введіть тут опис зображення

Ми також могли б використовувати перші осі для розміщення легенди, але використовувати bbox_transformосі легенди,

ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
lax.axis("off")

У такому підході нам не потрібно отримувати ручки легенди зовні, але нам потрібно вказати bbox_to_anchorаргумент.

Подальше читання та примітки:

  • Розгляньте посібник з легендою про matplotlib з деякими прикладами інших речей, які ви хочете зробити з легендами.
  • Деякі приклади коду розміщення легенд для пирогів можна безпосередньо знайти у відповіді на це запитання: Python - Legend перекривається з круговою діаграмою
  • locАргумент може приймати цифри замість рядка, які роблять дзвінки коротше, тим НЕ менш, вони не дуже інтуїтивно зіставляються один з одним. Ось відображення для довідки:

введіть тут опис зображення


Розміщення легенди в виділеній синергії на спеціальній осі субплоту fig.tight_layout. Якщо ви використовуєте plt.subplotsдля створення осей, просто надайте їм щось на зразок gridspec_kw={'height_ratios': [100, 1]}(або width_ratios), щоб осі легенди були крихітними ... Потім fig.tight_layout()розгорніть їх, щоб вони підходили. Принаймні для matplotlib 3.0.3.
travc

161

Просто зателефонуйте legend()після plot()дзвінка так:

# matplotlib
plt.plot(...)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

# Pandas
df.myCol.plot().legend(loc='center left', bbox_to_anchor=(1, 0.5))

Результати виглядатимуть приблизно так:

введіть тут опис зображення


4
працює при передачі тих же параметрів до matplotlib.pyplot.legend
kidmose

8
Чи це відрізає слова в легенді для когось іншого?
користувач1717828

85

Щоб розмістити легенду за межами ділянки, використовуйте locта bbox_to_anchorключові слова legend(). Наприклад, наступний код розмістить легенду праворуч від ділянки ділянки:

legend(loc="upper left", bbox_to_anchor=(1,1))

Для отримання додаткової інформації дивіться посібник з легендами


10
Гаразд - мені подобається реалізація, але коли я йду, щоб зберегти фігуру (не вручну змінюючи її розмір у вікні, що я не хочу робити щоразу), легенда відколюється. Будь-які ідеї, як я можу це виправити?
astromax

@astromax Я не впевнений, але, можливо, спробувати зателефонувати plt.tight_layout()?
Крістіан Аліс

81

Коротка відповідь: ви можете використовувати bbox_to_anchor+ bbox_extra_artists+ bbox_inches='tight'.


Більш довга відповідь: Ви можете використовувати bbox_to_anchor вручну, щоб вказати розташування вікна легенди, як вказали у відповідях деякі інші люди.

Однак звичайне питання полягає в тому, що поле "легенда" обрізане, наприклад:

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# Plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(all_x, all_y)

# Add legend, title and axis labels
lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
ax.set_title('Title')
ax.set_xlabel('x label')
ax.set_ylabel('y label')

fig.savefig('image_output.png', dpi=300, format='png')

введіть тут опис зображення

Щоб запобігти обрізанню поля легенди, при збереженні фігури ви можете використовувати параметри bbox_extra_artistsта bbox_inchesпопросити savefigвключити обрізані елементи до збереженого зображення:

fig.savefig('image_output.png', bbox_extra_artists=(lgd,), bbox_inches='tight')

Приклад (я змінив лише останній рядок, щоб додати 2 параметри fig.savefig()):

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# Plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(all_x, all_y)

# Add legend, title and axis labels
lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
ax.set_title('Title')
ax.set_xlabel('x label')
ax.set_ylabel('y label')    

fig.savefig('image_output.png', dpi=300, format='png', bbox_extra_artists=(lgd,), bbox_inches='tight')

введіть тут опис зображення

Я б хотів, щоб matplotlib спочатку дозволяв розташуватися поза полем для легенд, як це робить Matlab :

figure
x = 0:.2:12;
plot(x,besselj(1,x),x,besselj(2,x),x,besselj(3,x));
hleg = legend('First','Second','Third',...
              'Location','NorthEastOutside')
% Make the text of the legend italic and color it brown
set(hleg,'FontAngle','italic','TextColor',[.3,.2,.1])

введіть тут опис зображення


6
Дуже дякую! «Bbox_to_anchor», «bbox_extra_artist» і «» bbox_inches = "щільно» параметри були саме те , що мені потрібно , щоб змусити його працювати правильно Приголомшливо.!
Demitrian

6
Спасибі, але на самому справі bbox_inches='tight'відмінно працює для мене навіть без bbox_extra_artist
avtomaton

1
@avtomaton Дякую, добре знати, яку версію matplotlib ви використовуєте?
Франк Дернонкурт

1
@FranckDernoncourt python3, версія matplotlib 1.5.3
avtomaton

68

Окрім усіх чудових відповідей тут, новіші версії matplotlibта автоматичноpylab можуть визначити, куди слід поставити легенду, не втручаючись у сюжети , якщо це можливо.

pylab.legend(loc='best')

Це автоматично віддаляє легенду від даних, якщо це можливо! Порівняйте використання loc = 'best'

Однак якщо легенди немає де розмістити легенду, не перекриваючи дані, то вам захочеться спробувати одну з інших відповідей; використання loc="best"ніколи не поставить легенду поза сюжетом.


2
Дякую, що вказали на це! Я шукав це кілька років тому і не знайшов, і це щось, що насправді полегшує моє життя.
Едгар Н

4
цей варіант корисний, але не дає відповіді на запитання, тому я прийняв рішення. наскільки я можу сказати, найкраще ніколи не ставить легенду поза сюжетом
Томмі

3
@Tommy: У коментарях ОП (яких, здається, зараз немає) було чітко уточнено, що ОП хоче, щоб легенда не висвітлювала дані графіків, і він вважав, що поза сюжетом це єдиний спосіб зробити це. Це можна побачити у відповідях мефатії, Матео Санчеса, Бастіана та Радтека. OP попросив X, але він хотів Y .
dotancohen

1
Власне, ні. Він спеціально попросив, щоб легенда була поза сюжетом. Це в назві питання;) "Як викласти легенду з сюжету".
durbachit

4
Це не гарантує, що легенда не затьмарює дані. Просто зробіть дуже щільний сюжет - легенди немає де поставити. Наприклад, спробуйте це ... з numpy import arange, sin, pi import matplotlib.pyplot як plt t = arange (0.0, 100.0, 0.01) fig = plt.figure (1) ax1 = fig.add_subplot (211) ax1. splitter (t, sin (2 * pi * t), label = 'test') ax1.grid (True) # ax1.set_ylim ((- 2, 2)) ax1.set_ylabel ('1 Гц') ax1.set_title ( 'Синусоїда або дві') для мітки в ax1.get_xticklabels (): label.set_color ('r') plt.legend (loc = 'best') plt.show ()
adam.r

56

Коротка відповідь : Закликайте перетягувати легенду та інтерактивно переміщуйте її куди завгодно:

ax.legend().draggable()

Довга відповідь : Якщо ви віддаєте перевагу розміщенню легенди інтерактивно / вручну, а не програмно, ви можете переключити режим перетягування легенди, щоб ви могли перетягнути її куди завгодно. Перевірте приклад нижче:

import matplotlib.pylab as plt
import numpy as np
#define the figure and get an axes instance
fig = plt.figure()
ax = fig.add_subplot(111)
#plot the data
x = np.arange(-5, 6)
ax.plot(x, x*x, label='y = x^2')
ax.plot(x, x*x*x, label='y = x^3')
ax.legend().draggable()
plt.show()

Не впевнений, що розумію це повністю. Як я "перетягую" легенду туди, куди хочу з цим? Я використовую Python 3.6 та Jupyter Notebook
sb2020

14

Не зовсім те, про що ви просили, але я виявив, що це альтернатива тій же проблемі. Зробіть легенду напівпрозорою, наприклад: сюжет matplotlib з напівпрозорою легендою та напівпрозорим текстовим полем

Зробіть це за допомогою:

fig = pylab.figure()
ax = fig.add_subplot(111)
ax.plot(x,y,label=label,color=color)
# Make the legend transparent:
ax.legend(loc=2,fontsize=10,fancybox=True).get_frame().set_alpha(0.5)
# Make a transparent text box
ax.text(0.02,0.02,yourstring, verticalalignment='bottom',
                     horizontalalignment='left',
                     fontsize=10,
                     bbox={'facecolor':'white', 'alpha':0.6, 'pad':10},
                     transform=self.ax.transAxes)

8

Як зазначалося, ви також можете розмістити легенду у сюжеті, а також трохи відімкнути її до краю. Ось приклад використання API Plotly Python , зробленого за допомогою ноутбука IPython . Я в команді.

Для початку вам потрібно встановити необхідні пакети:

import plotly
import math
import random
import numpy as np

Потім встановіть Plotly:

un='IPython.Demo'
k='1fw3zw2o13'
py = plotly.plotly(username=un, key=k)


def sin(x,n):
sine = 0
for i in range(n):
    sign = (-1)**i
    sine = sine + ((x**(2.0*i+1))/math.factorial(2*i+1))*sign
return sine

x = np.arange(-12,12,0.1)

anno = {
'text': '$\\sum_{k=0}^{\\infty} \\frac {(-1)^k x^{1+2k}}{(1 + 2k)!}$',
'x': 0.3, 'y': 0.6,'xref': "paper", 'yref': "paper",'showarrow': False,
'font':{'size':24}
}

l = {
'annotations': [anno], 
'title': 'Taylor series of sine',
'xaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
'yaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
'legend':{'font':{'size':16},'bordercolor':'white','bgcolor':'#fcfcfc'}
}

py.iplot([{'x':x, 'y':sin(x,1), 'line':{'color':'#e377c2'}, 'name':'$x\\\\$'},\
      {'x':x, 'y':sin(x,2), 'line':{'color':'#7f7f7f'},'name':'$ x-\\frac{x^3}{6}$'},\
      {'x':x, 'y':sin(x,3), 'line':{'color':'#bcbd22'},'name':'$ x-\\frac{x^3}{6}+\\frac{x^5}{120}$'},\
      {'x':x, 'y':sin(x,4), 'line':{'color':'#17becf'},'name':'$ x-\\frac{x^5}{120}$'}], layout=l)

Це створює ваш графік і дає можливість зберегти легенду в межах самого сюжету. За замовчуванням для легенди, якщо вона не встановлена, є розміщення її в сюжеті, як показано тут.

введіть тут опис зображення

Для альтернативного розміщення ви можете щільно вирівняти край графіка та межу легенди та видалити межі для кращого прилягання.

введіть тут опис зображення

Ви можете переміщувати та перевпорядковувати легенду та графік за допомогою коду чи за допомогою графічного інтерфейсу. Для зміщення легенди у вас є такі параметри, щоб розташувати легенду всередині графіка, призначивши значення x і y <= 1. Наприклад:

  • {"x" : 0,"y" : 0} - знизу зліва
  • {"x" : 1, "y" : 0} - Праворуч знизу
  • {"x" : 1, "y" : 1} - Вгорі праворуч
  • {"x" : 0, "y" : 1} - Вгорі зліва
  • {"x" :.5, "y" : 0} - Нижній центр
  • {"x": .5, "y" : 1} - Топ-центр

У цьому випадку ми вибираємо верхній правий верх legendstyle = {"x" : 1, "y" : 1}, також описаний у документації :

введіть тут опис зображення


3

Щось у цьому напрямку працювало для мене. Починаючи з трохи коду, взятого у Джо, цей метод змінює ширину вікна, щоб автоматично підходити до легенди праворуч від фігури.

import matplotlib.pyplot as plt
import numpy as np

plt.ion()

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$'%i)

# Put a legend to the right of the current axis
leg = ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

plt.draw()

# Get the ax dimensions.
box = ax.get_position()
xlocs = (box.x0,box.x1)
ylocs = (box.y0,box.y1)

# Get the figure size in inches and the dpi.
w, h = fig.get_size_inches()
dpi = fig.get_dpi()

# Get the legend size, calculate new window width and change the figure size.
legWidth = leg.get_window_extent().width
winWidthNew = w*dpi+legWidth
fig.set_size_inches(winWidthNew/dpi,h)

# Adjust the window size to fit the figure.
mgr = plt.get_current_fig_manager()
mgr.window.wm_geometry("%ix%i"%(winWidthNew,mgr.window.winfo_height()))

# Rescale the ax to keep its original size.
factor = w*dpi/winWidthNew
x0 = xlocs[0]*factor
x1 = xlocs[1]*factor
width = box.width*factor
ax.set_position([x0,ylocs[0],x1-x0,ylocs[1]-ylocs[0]])

plt.draw()

Я вважав це досить корисним, і воно працювало на мене. Зауважте, що якщо ви перебуваєте в wx backkend (наприклад, використовуєте windows), замініть mgr.window.wm_geometry ("% ix% i"% (winWidthNew, mgr.window.winfo_height ()) на mgr.window.SetClientSizeWH (winWidthNew , winHeightNew) тощо)
Єзекіїль Круглик

Якщо ви використовуєте сервер Qt4Agg (який є типовим для моєї установки Linux на matplotlib), замініть рядок mgr.window.wm_geometry(...)на mgr.window.setFixedWidth(winWidthNew).
Філіп С.

І, як я нещодавно з’ясував, якщо ви використовуєте бекенд, який не показує жодного вікна, призначеного для збереження прямо у файл (як, наприклад, SVG та AGG пакети), просто пропустіть вікно повністю змінивши розмір. fig.set_size_inches(...)піклується про необхідний вам розмір.
Філіп С.

3

Це питання варто оновити, оскільки новіші версії Matplotlib значно полегшили позиціонування легенди поза сюжетом. Цей приклад я створив з версією Matplotlib 3.1.1.

Користувачі можуть передавати параметр 2-х координат до locпараметра, щоб розташувати легенду в будь-якому місці обмежувального поля. Єдиний gotcha - вам потрібно запустити, plt.tight_layout()щоб отримати matplotlib для перерахунку розмірів ділянки, щоб видно легенда:

import matplotlib.pyplot as plt

plt.plot([0, 1], [0, 1], label="Label 1")
plt.plot([0, 1], [0, 2], label='Label 2')

plt.legend(loc=(1.05, 0.5))
plt.tight_layout()

Це призводить до наступного сюжету:

сюжет з легендою зовні

Список літератури:


2

Ви також можете спробувати figlegend. Можна створити легенду, незалежну від будь-якого об'єкта Axes. Однак вам може знадобитися створити кілька "манекенів" Шляхів, щоб переконатися, що форматування об'єктів правильно передається.


1

Ось приклад із навчального посібника з matplotlib, знайденого тут . Це один із найпростіших прикладів, але я додав прозорості до легенди та додав plt.show (), щоб ви могли вставити це у інтерактивну оболонку та отримати результат:

import matplotlib.pyplot as plt
p1, = plt.plot([1, 2, 3])
p2, = plt.plot([3, 2, 1])
p3, = plt.plot([2, 3, 1])
plt.legend([p2, p1, p3], ["line 1", "line 2", "line 3"]).get_frame().set_alpha(0.5)
plt.show()

1

Рішення, яке працювало для мене, коли у мене була величезна легенда, полягало в тому, щоб використовувати додатковий порожній макет зображення. У наступному прикладі я зробив 4 ряди, а внизу малюю зображення зі зміщенням для легенди (bbox_to_anchor), вгорі воно не розрізається.

f = plt.figure()
ax = f.add_subplot(414)
lgd = ax.legend(loc='upper left', bbox_to_anchor=(0, 4), mode="expand", borderaxespad=0.3)
ax.autoscale_view()
plt.savefig(fig_name, format='svg', dpi=1200, bbox_extra_artists=(lgd,), bbox_inches='tight')

1

Ось ще одне рішення, подібне до додавання bbox_extra_artistsта bbox_inches, коли не потрібно мати зайвих виконавців у межах вашихsavefig дзвінка. Я придумав це, оскільки генерую більшість своїх сюжетних функцій всередині.

Замість того, щоб додавати всі ваші доповнення до обмежувального поля, коли ви хочете їх виписати, ви можете додати їх достроково Figureхудожникам. Використовуючи щось подібне до відповіді Франка Дернонкура вище :

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# plotting function
def gen_plot(x, y):
    fig = plt.figure(1)
    ax = fig.add_subplot(111)
    ax.plot(all_x, all_y)
    lgd = ax.legend( [ "Lag " + str(lag) for lag in all_x], loc="center right", bbox_to_anchor=(1.3, 0.5))
    fig.artists.append(lgd) # Here's the change
    ax.set_title("Title")
    ax.set_xlabel("x label")
    ax.set_ylabel("y label")
    return fig

# plotting
fig = gen_plot(all_x, all_y)

# No need for `bbox_extra_artists`
fig.savefig("image_output.png", dpi=300, format="png", bbox_inches="tight")

Ось створений сюжет.


-1

не знаю, чи ви вже розібралися зі своєю проблемою ... напевно, так, але ... я просто використав рядок "назовні" для розташування, як у matlab. Я імпортував пілаб з matplotlib. дивіться код наступним чином:

from matplotlib as plt
from matplotlib.font_manager import FontProperties
...
...
t = A[:,0]
sensors = A[:,index_lst]

for i in range(sensors.shape[1]):
    plt.plot(t,sensors[:,i])

plt.xlabel('s')
plt.ylabel('°C')
lgd = plt.legend(b,loc='center left', bbox_to_anchor=(1, 0.5),fancybox = True, shadow = True)

Клацніть, щоб побачити сюжет

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.