Как перенести легенду за пределы участка в море? [Дубликат]

Сделать виртуальный дескриптор виртуальным, когда ваш класс является полиморфным.

604
задан ImportanceOfBeingErnest 7 July 2018 в 15:04
поделиться

16 ответов

Создать свойства шрифта

from matplotlib.font_manager import FontProperties

fontP = FontProperties()
fontP.set_size('small')
legend([plot1], "title", prop=fontP)
89
ответ дан MSeifert 15 August 2018 в 21:26
поделиться
  • 1
    Спасибо Navi .. Но я получаю сообщение об ошибке «FontProperties» не определен. Не могли бы вы мне помочь... – pottigopi 15 January 2011 в 17:33
  • 2
    Вам нужно добавить этот импорт: из matplotlib.font_manager импортировать FontProperties – Navi 15 January 2011 в 17:38
  • 3
    использование из matplotlib.font_manager import FontProperties НЕ импортирует matplotlib.font_manager как FontProperties. То, что вы делаете, - это псевдоним («переименование») matplotlib.font_manager в FontProperties, поэтому вызов fontP = FontProperties () на самом деле вызывает matplotlib.font_manager, который не может быть вызван. – ianalis 15 January 2011 в 18:01
  • 4
    что plot1 в этом ответе? – Paul H 13 January 2018 в 09:21
  • 5
    что legend в этом ответе? – Richard 24 July 2018 в 14:47

Не то, что вы просили, но я нашел альтернативу для той же проблемы. Сделайте легенду полупрозрачной, например: matplotlib plot with semi transparent legend and semitransparent text box [/g0]

Сделайте это с помощью:

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)
11
ответ дан Bastiaan 15 August 2018 в 21:26
поделиться

Вот еще одно решение, похожее на добавление 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")

Вот генерируемый сюжет.

0
ответ дан Community 15 August 2018 в 21:26
поделиться

Решение, которое работало для меня, когда у меня была огромная легенда, заключалась в использовании дополнительного пустого макета изображения. В следующем примере я сделал 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
ответ дан Crystal 15 August 2018 в 21:26
поделиться

В дополнение ко всем превосходным ответам здесь более новые версии matplotlib и pylab могут автоматически определять, где положить легенду, не мешая графикам.

pylab.legend(loc='best')

Это автоматически помещается легенда вне сюжета! Compare the use of loc='best' [/g0]

46
ответ дан dotancohen 15 August 2018 в 21:26
поделиться
  • 1
    Спасибо, что указали это! Я искал это несколько лет назад и не нашел его, и это то, что действительно облегчает мою жизнь. – Edgar H 23 August 2015 в 10:37
  • 2
    этот вариант полезен, но не отвечает на вопрос, поэтому я ниспровергаю. насколько я могу судить, лучше никогда не ставить легенду за пределы сюжета – Tommy 9 September 2015 в 12:01
  • 3
    @Tommy: В комментариях OP (которые, кажется, сейчас нет) было четко разъяснено, что OP хочет, чтобы легенда не покрывала данные графа, и он думал, что вне сюжета был единственный способ сделать это. Вы можете видеть это в ответах от mefathy, Mateo Sanchez, Bastiaan и radtek. OP попросил X, но он хотел Y . – dotancohen 9 September 2015 в 13:19
  • 4
    Вообще-то нет. Он специально попросил, чтобы легенда была вне сюжета. Это от имени вопроса;) «Как вывести легенду из сюжета». – durbachit 30 August 2016 в 03:09
  • 5
    Это не гарантирует, что легенда не скрывает данные. Просто сделайте очень плотный заговор - нет места, чтобы поставить легенду. Например, попробуйте это ... из 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. разброс (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 8 February 2018 в 17:34

Короткий ответ: вы можете использовать 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')

enter image description here [/g1]

Чтобы предотвратить когда вы сохраняете фигуру, вы можете использовать параметры 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')

enter image description here [/g2]

Желаю 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])

enter image description here [/g3]

70
ответ дан Franck Dernoncourt 15 August 2018 в 21:26
поделиться
  • 1
    Спасибо огромное! & Quot; bbox_to_anchor "," bbox_extra_artist " и "bbox_inches =" tight " параметры были именно тем, что мне нужно для правильной работы. Потрясающие! – Demitrian 31 August 2014 в 15:04
  • 2
    Спасибо, но на самом деле bbox_inches='tight' отлично работает для меня даже без bbox_extra_artists – avtomaton 8 November 2016 в 06:16
  • 3
    @avtomaton Спасибо, хорошо знать, какую версию matplotlib вы используете? – Franck Dernoncourt 8 November 2016 в 18:28
  • 4
    @FranckDernoncourt python3, matplotlib версия 1.5.3 – avtomaton 9 November 2016 в 05:49
  • 5
    @avtomaton Я вижу, я думаю, что последние версии облегчают жизнь. – Franck Dernoncourt 9 November 2016 в 06:09

Существует несколько способов сделать то, что вы хотите. Чтобы добавить к уже сказанным @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 text [/g2]

Если мы делаем то же самое, но используем аргумент ключевого слова 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 text [/g3]

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

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 text [/g4]

Кроме того, вы можете уменьшить ширину текущего графика и поставить легенду полностью за пределами оси рисунка:

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 text [/g5]

И аналогичным образом вы можете сжать график по вертикали и поместить горизонтальный легенда внизу:

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 text [/g6]

Посмотрите на руководство по легенде matplotlib . Вы также можете взглянуть на plt.figlegend() . Надеюсь, что это поможет, во всяком случае!

1277
ответ дан IanS 15 August 2018 в 21:26
поделиться
  • 1
    Это должно быть сделано в качестве примера или добавлено в галерею на сайте matplotlib. – jlconlin 11 June 2012 в 22:20
  • 2
    Если у кого-то возникли проблемы с этим, обратите внимание, что tight_layout () вызовет проблемы! – Matthew G. 20 February 2013 в 01:50
  • 3
    отличный ответ! правильная ссылка на документ - matplotlib.org/users/legend_guide.html#legend-location – meduz 23 October 2013 в 10:01
  • 4
    как полноту, вы можете сказать, что в целом (суммировано из документа) " bbox_to_anchor представляет собой набор из 4 поплавков (x, y, ширина, высота bbox) или кортеж из 2 поплавков (x, y) в нормализованных координатах осей. & Quot; – meduz 23 October 2013 в 10:03
  • 5
    Обратите внимание: если вы хотите сохранить фигуру в файл, вы, вероятно, должны сохранить возвращенный объект, то есть legend = ax.legend() и позже fig.savefig(bbox_extra_artists=(legend,)) – coldfix 5 October 2017 в 17:30
323
ответ дан ImportanceOfBeingErnest 15 August 2018 в 21:26
поделиться

Что-то в этом направлении работало для меня. Начиная с небольшого кода, взятого из Joe, этот метод изменяет ширину окна, чтобы автоматически поместить легенду справа от рисунка.

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()
3
ответ дан Martin 15 August 2018 в 21:26
поделиться
  • 1
    Я нашел это весьма полезным, и это сработало для меня. Обратите внимание: если вы находитесь в wx-сервере (например, с помощью окон), замените mgr.window.wm_geometry («% ix% i»% (winWidthNew, mgr.window.winfo_height ())) с помощью mgr.window.SetClientSizeWH ( winWidthNew, winHeightNew) или тому подобное – Ezekiel Kruglick 18 February 2014 в 23:21
  • 2
    Если вы используете бэкенд Qt4Agg (который по умолчанию используется в моей установке matplotlib для Linux), замените строку mgr.window.wm_geometry(...) на mgr.window.setFixedWidth(winWidthNew). – Filip S. 30 April 2014 в 07:47
  • 3
    И, как я только что узнал, если вы используете бэкэнд, который не показывает никаких окон, предназначенных для сохранения прямо в файл (например, SVG и AGG), просто пропустите изменение размера окна. fig.set_size_inches(...) позаботится о необходимости изменения размера. – Filip S. 30 April 2014 в 07:55

Как уже отмечалось, вы также можете поместить легенду в сюжет или немного от нее до края. Ниже приведен пример использования Plotly Python API , сделанного с IPython Notebook . Я в команде.

Чтобы начать, вы захотите установить необходимые пакеты:

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)

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

enter image description here [/g3]

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

enter image description here [/g4]

Вы можете перемещать и переписывать легенду и график с помощью кода или с помощью графического интерфейса. Чтобы переместить легенду, у вас есть следующие параметры, чтобы расположить легенду внутри графика, назначив значения х и у символа & lt; = 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}, также описанный в документация :

enter image description here [/g5]

7
ответ дан Mateo Sanchez 15 August 2018 в 21:26
поделиться

Краткий ответ: вызывать перетаскивание по легенде и интерактивно перемещать его туда, где вы хотите:

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()
50
ответ дан mefathy 15 August 2018 в 21:26
поделиться

Вот пример из учебника 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
ответ дан radtek 15 August 2018 в 21:26
поделиться
  • 1
    Упреждение за лукавую распаковку объектов линии. – Mad Physicist 4 April 2016 в 17:07

Чтобы поместить легенду за пределы области графика, используйте слова loc и bbox_to_anchor legend (). Например, следующий код поместит легенду справа от области графика:

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

Для получения дополнительной информации см. Руководство по легенде

45
ответ дан RegularlyScheduledProgramming 15 August 2018 в 21:26
поделиться
  • 1
    Хорошо - мне нравится реализация, но когда я иду, чтобы сохранить фигуру (без изменения ее вручную в окне, которое я не хочу делать каждый раз), легенда прерывается. Любые идеи о том, как я могу это исправить? – astromax 5 July 2015 в 15:28
  • 2
    @astromax Я не уверен, но, возможно, попробую позвонить plt.tight_layout()? – ianalis 5 July 2015 в 19:07

Если вы используете функцию обложки Pandas plot() и хотите разместить легенду снаружи, то здесь очень простой способ:

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

Мы просто вызываем цепочку legend() после plot().

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

enter image description here [/g0]

108
ответ дан ShitalShah 15 August 2018 в 21:26
поделиться
  • 1
    работает при передаче тех же параметров в matplotlib.pyplot.legend, а также – kidmose 25 October 2016 в 09:54

Вы также можете попробовать figlegend. Можно создать легенду, независимую от любого объекта Axes. Однако вам может потребоваться создать несколько «фиктивных» путей, чтобы убедиться, что форматирование объектов передается правильно.

2
ответ дан Uri Laserson 15 August 2018 в 21:26
поделиться

не знаю, если вы уже разобрали свою проблему ... возможно, да, но ... Я просто использовал строку «outside» для местоположения, например, в Matlab. Я импортировал pylab из 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)

Нажмите, чтобы просмотреть график

0
ответ дан Ziuccia 15 August 2018 в 21:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: