Как убрать легенду из сюжета - PullRequest
779 голосов
/ 15 января 2011

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

  1. Я хочу, чтобы поле легенды находилось за пределами области сюжета.(Я хочу, чтобы легенда находилась снаружи с правой стороны области графика).
  2. В любом случае я уменьшу размер шрифта текста внутри поля легенды, чтобы его размербудь маленьким.

Ответы [ 16 ]

3 голосов
/ 21 декабря 2013

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

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()
2 голосов
/ 17 января 2011

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

1 голос
/ 27 января 2017

Вот еще одно решение, похожее на добавление 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 голос
/ 28 августа 2016

Решение, которое работало для меня, когда у меня была огромная легенда, заключалось в использовании дополнительного пустого макета изображения.В следующем примере я сделал 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 голос
/ 10 июня 2014

Вот пример из учебника 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()
0 голосов
/ 15 марта 2017

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

Нажмите, чтобы увидеть участок

...