简体   繁体   English

如何将图例排除在情节之外

[英]How to put the legend out of the plot

I have a series of 20 plots (not subplots) to be made in a single figure.我在一个图中制作了一系列 20 个图(不是子图)。 I want the legend to be outside of the box.我希望图例在框外。 At the same time, I do not want to change the axes, as the size of the figure gets reduced.同时,我不想改变轴,因为图形的大小变小了。 Kindly help me for the following queries:请帮助我解决以下问题:

  1. I want to keep the legend box outside the plot area.我想将图例框保留在绘图区域之外。 (I want the legend to be outside at the right side of the plot area). (我希望图例位于情节区域的右侧)。
  2. Is there anyway that I reduce the font size of the text inside the legend box, so that the size of the legend box will be small.无论如何,我是否减小了图例框内文本的字体大小,以便图例框的大小变小。

There are a number of ways to do what you want.有很多方法可以做你想做的事。 To add to what @inalis and @Navi already said, you can use the bbox_to_anchor keyword argument to place the legend partially outside the axes and/or decrease the font size.要添加@inalis 和@Navi 已经说过的内容,您可以使用bbox_to_anchor关键字参数将图例部分放置在轴之外和/或减小字体大小。

Before you consider decreasing the font size (which can make things awfully hard to read), try playing around with placing the legend in different places:在考虑减小字体大小(这会使阅读变得非常困难)之前,请尝试将图例放置在不同的位置:

So, let's start with a generic example:因此,让我们从一个通用示例开始:

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

替代文字

If we do the same thing, but use the bbox_to_anchor keyword argument we can shift the legend slightly outside the axes boundaries:如果我们做同样的事情,但使用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()

替代文字

Similarly, make the legend more horizontal and/or put it at the top of the figure (I'm also turning on rounded corners and a simple drop shadow):同样,使图例更加水平和/或将其放在图的顶部(我还打开了圆角和简单的投影):

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

替代文字

Alternatively, shrink the current plot's width, and put the legend entirely outside the axis of the figure (note: if you use tight_layout() , then leave out ax.set_position() :或者,缩小当前绘图的宽度,并将图例完全放在图形轴之外(注意:如果您使用tight_layout() ,则省略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()

替代文字

And in a similar manner, shrink the plot vertically, and put a horizontal legend at the bottom:并以类似的方式垂直缩小图,并在底部放置一个水平图例:

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

替代文字

Have a look at the matplotlib legend guide .看看matplotlib图例指南 You might also take a look at plt.figlegend() .你也可以看看plt.figlegend()

Placing the legend ( bbox_to_anchor )放置图例( bbox_to_anchor

A legend is positioned inside the bounding box of the axes using the loc argument to plt.legend .使用plt.legendloc参数将图例定位在轴的边界框内。
Eg loc="upper right" places the legend in the upper right corner of the bounding box, which by default extents from (0,0) to (1,1) in axes coordinates (or in bounding box notation (x0,y0, width, height)=(0,0,1,1) ).例如loc="upper right"的地方在边界框的右上角,图例,其通过从默认盘区(0,0)(1,1)在轴坐标(或在边界框表示法(x0,y0, width, height)=(0,0,1,1) )。

To place the legend outside of the axes bounding box, one may specify a tuple (x0,y0) of axes coordinates of the lower left corner of the legend.要将图例放置在轴边界框之外,可以指定图例左下角轴坐标的元组(x0,y0)

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

A more versatile approach is to manually specify the bounding box into which the legend should be placed, using the bbox_to_anchor argument.一种更通用的方法是使用bbox_to_anchor参数手动指定放置图例的边界框。 One can restrict oneself to supply only the (x0, y0) part of the bbox.可以限制自己只提供 bbox 的(x0, y0)部分。 This creates a zero span box, out of which the legend will expand in the direction given by the loc argument.这将创建一个零跨度框,其中图例将在loc参数给定的方向上扩展。 Eg例如

plt.legend(bbox_to_anchor=(1.04,1), loc="upper left")

places the legend outside the axes, such that the upper left corner of the legend is at position (1.04,1) in axes coordinates.将图例放在坐标区之外,这样图例的左上角位于坐标区坐标中的(1.04,1)位置。

Further examples are given below, where additionally the interplay between different arguments like mode and ncols are shown.下面给出了更多示例,其中还显示了不同参数(如modencols之间的相互作用。

在此处输入图片说明

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

Details about how to interpret the 4-tuple argument to bbox_to_anchor , as in l4 , can be found in this question .有关如何将 4 元组参数解释为bbox_to_anchor ,如在l4 ,可以在这个问题中找到。 The mode="expand" expands the legend horizontally inside the bounding box given by the 4-tuple. mode="expand"在四元组给出的边界框内水平扩展图例。 For a vertically expanded legend, see this question .有关垂直展开的图例,请参阅此问题

Sometimes it may be useful to specify the bounding box in figure coordinates instead of axes coordinates.有时在图形坐标而不是轴坐标中指定边界框可能很有用。 This is shown in the example l5 from above, where the bbox_transform argument is used to put the legend in the lower left corner of the figure.这在上面的示例l5显示,其中bbox_transform参数用于将图例放在图的左下角。

Postprocessing后期处理

Having placed the legend outside the axes often leads to the undesired situation that it is completely or partially outside the figure canvas.将图例放在轴外通常会导致不希望出现的情况,即它完全或部分位于图形画布之外。

Solutions to this problem are:这个问题的解决方法是:

  • Adjust the subplot parameters调整子图参数
    One can adjust the subplot parameters such, that the axes take less space inside the figure (and thereby leave more space to the legend) by using plt.subplots_adjust .可以通过使用plt.subplots_adjust调整子图参数,使轴在图形内占用更少的空间(从而为图例留下更多空间)。 Eg例如

     plt.subplots_adjust(right=0.7)

leaves 30% space on the right-hand side of the figure, where one could place the legend.在图的右侧留出 30% 的空间,可以在其中放置图例。

  • Tight layout紧凑的布局
    Using plt.tight_layout Allows to automatically adjust the subplot parameters such that the elements in the figure sit tight against the figure edges.使用plt.tight_layout允许自动调整子图参数,使图形中的元素紧靠图形边缘。 Unfortunately, the legend is not taken into account in this automatism, but we can supply a rectangle box that the whole subplots area (including labels) will fit into.不幸的是,在这个自动机制中没有考虑图例,但是我们可以提供一个矩形框,整个子图区域(包括标签)都可以放入其中。

     plt.tight_layout(rect=[0,0,0.75,1])
  • Saving the figure with bbox_inches = "tight"使用bbox_inches = "tight"保存图形
    The argument bbox_inches = "tight" to plt.savefig can be used to save the figure such that all artist on the canvas (including the legend) are fit into the saved area.这个论点bbox_inches = "tight"plt.savefig可以用来保存数字使得画布(包括图例)上的所有艺术家被装配到已保存的区域。 If needed, the figure size is automatically adjusted.如果需要,图形大小会自动调整。

     plt.savefig("output.png", bbox_inches="tight")
  • automatically adjusting the subplot params自动调整子图参数
    A way to automatically adjust the subplot position such that the legend fits inside the canvas without changing the figure size can be found in this answer: Creating figure with exact size and no padding (and legend outside the axes)可以在此答案中找到一种自动调整子图位置以使图例适合画布而不更改图形大小的方法:创建具有精确大小且无填充(以及轴外的图例)的图形

Comparison between the cases discussed above:上面讨论的案例之间的比较:

在此处输入图片说明

Alternatives备择方案

A figure legend一个人物传奇

One may use a legend to the figure instead of the axes, matplotlib.figure.Figure.legend .可以使用图形的图例而不是轴matplotlib.figure.Figure.legend This has become especially useful for matplotlib version >=2.1, where no special arguments are needed这对于不需要特殊参数的 matplotlib 版本 >=2.1 尤其有用

fig.legend(loc=7) 

to create a legend for all artists in the different axes of the figure.为图形不同轴上的所有艺术家创建图例。 The legend is placed using the loc argument, similar to how it is placed inside an axes, but in reference to the whole figure - hence it will be outside the axes somewhat automatically.图例使用loc参数放置,类似于将其放置在轴内的方式,但参考整个图形 - 因此它会在某种程度上自动位于轴外。 What remains is to adjust the subplots such that there is no overlap between the legend and the axes.剩下的就是调整子图,使图例和轴之间没有重叠。 Here the point "Adjust the subplot parameters" from above will be helpful.在这里,上面的“调整子图​​参数”这一点会有所帮助。 An example:一个例子:

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

在此处输入图片说明

Legend inside dedicated subplot axes专用子图轴内的图例

An alternative to using bbox_to_anchor would be to place the legend in its dedicated subplot axes ( lax ).使用bbox_to_anchor的另一种方法是将图例放置在其专用的子图轴 ( lax ) 中。 Since the legend subplot should be smaller than the plot, we may use gridspec_kw={"width_ratios":[4,1]} at axes creation.由于图gridspec_kw={"width_ratios":[4,1]}图应该小于图,我们可以在轴创建时使用gridspec_kw={"width_ratios":[4,1]} We can hide the axes lax.axis("off") but still put a legend in. The legend handles and labels need to obtained from the real plot via h,l = ax.get_legend_handles_labels() , and can then be supplied to the legend in the lax subplot, lax.legend(h,l) .我们可以隐藏轴lax.axis("off")但仍然放置图例。图例句柄和标签需要通过h,l = ax.get_legend_handles_labels()从真实图中获得,然后可以提供给lax子图中的图例, lax.legend(h,l) A complete example is below.一个完整的例子如下。

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

This produces a plot, which is visually pretty similar to the plot from above:这会产生一个图,它在视觉上与上面的图非常相似:

在此处输入图片说明

We could also use the first axes to place the legend, but use the bbox_transform of the legend axes,我们也可以使用第一个轴来放置图例,但使用图例轴的bbox_transform

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

In this approach, we do not need to obtain the legend handles externally, but we need to specify the bbox_to_anchor argument.在这种方法中,我们不需要从外部获取图例句柄,但需要指定bbox_to_anchor参数。

Further reading and notes:进一步阅读和注意事项:

  • Consider the matplotlib legend guide with some examples of other stuff you want to do with legends.考虑 matplotlib 的图例指南,其中包含一些您想对图例进行处理的其他内容的示例。
  • Some example code for placing legends for pie charts may directly be found in answer to this question: Python - Legend overlaps with the pie chart在回答这个问题时可以直接找到一些用于放置饼图图例的示例代码: Python - Legend重叠与饼图
  • The loc argument can take numbers instead of strings, which make calls shorter, however, they are not very intuitively mapped to each other. loc参数可以使用数字而不是字符串,这使得调用更短,但是,它们之间的映射并不是很直观。 Here is the mapping for reference:以下是参考映射:

在此处输入图片说明

Just call legend() call after the plot() call like this:只需在plot()调用之后调用legend()调用,如下所示:

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

Results would look something like this:结果看起来像这样:

在此处输入图片说明

import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

fontP = FontProperties()
fontP.set_size('xx-small')

p1, = plt.plot([1, 2, 3], label='Line 1')
p2, = plt.plot([3, 2, 1], label='Line 2')
plt.legend(handles=[p1, p2], title='title', bbox_to_anchor=(1.05, 1), loc='upper left', prop=fontP)

在此处输入图片说明

  • As noted by Mateen Ulhaq , fontsize='xx-small' also works, without importing FontProperties .正如Mateen Ulhaq所指出的, fontsize='xx-small'也可以工作,而无需导入FontProperties
plt.legend(handles=[p1, p2], title='title', bbox_to_anchor=(1.05, 1), loc='upper left', fontsize='xx-small')

To place the legend outside the plot area, use loc and bbox_to_anchor keywords of legend() .要将图例放置在绘图区域之外,请使用legend() locbbox_to_anchor关键字。 For example, the following code will place the legend to the right of the plot area:例如,以下代码会将图例放置在绘图区域的右侧:

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

For more info, see the legend guide有关更多信息,请参阅图例指南

Short answer: you can use bbox_to_anchor + bbox_extra_artists + bbox_inches='tight' .简短回答:您可以使用bbox_to_anchor + bbox_extra_artists + bbox_inches='tight'


Longer answer: You can use bbox_to_anchor to manually specify the location of the legend box, as some other people have pointed out in the answers.更长的答案:您可以使用bbox_to_anchor手动指定图例框的位置,正如其他一些人在答案中指出的那样。

However, the usual issue is that the legend box is cropped, eg:但是,通常的问题是图例框被裁剪,例如:

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

在此处输入图片说明

In order to prevent the legend box from getting cropped, when you save the figure you can use the parameters bbox_extra_artists and bbox_inches to ask savefig to include cropped elements in the saved image:为了防止图例框被裁剪,保存图形时可以使用参数bbox_extra_artistsbbox_inches要求savefig在保存的图像中包含裁剪的元素:

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

Example (I only changed the last line to add 2 parameters to fig.savefig() ):示例(我只更改了最后一行以将 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')

在此处输入图片说明

I wish that matplotlib would natively allow outside location for the legend box as Matlab does :我希望 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])

在此处输入图片说明

In addition to all the excellent answers here, newer versions of matplotlib and pylab can automatically determine where to put the legend without interfering with the plots , if possible.除了这里的所有优秀答案之外,如果可能,新版本的matplotlibpylab可以自动确定放置图例的位置,而不会干扰绘图

pylab.legend(loc='best')

This will automatically place the legend away from the data if possible!如果可能,这将自动将图例远离数据!loc='best' 的使用对比

However, if there is no place to put the legend without overlapping the data, then you'll want to try one of the other answers;但是,如果没有地方放置图例而不重叠数据,那么您将想要尝试其他答案之一; using loc="best" will never put the legend outside of the plot.使用loc="best"永远不会将图例放在情节之外

Short Answer : Invoke draggable on the legend and interactively move it wherever you want:简短回答:在图例上调用可拖动并以交互方式将其移动到您想要的任何位置:

ax.legend().draggable()

Long Answer : If you rather prefer to place the legend interactively/manually rather than programmatically, you can toggle the draggable mode of the legend so that you can drag it to wherever you want.长答案:如果您更喜欢以交互/手动方式而不是以编程方式放置图例,您可以切换图例的可拖动模式,以便您可以将其拖动到任何您想要的位置。 Check the example below:检查下面的例子:

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

Not exactly what you asked for, but I found it's an alternative for the same problem.不完全是您所要求的,但我发现它是同一问题的替代方案。 Make the legend semi-transparant, like so:使图例半透明,如下所示: 带有半透明图例和半透明文本框的 matplotlib 图

Do this with:这样做:

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)

As noted, you could also place the legend in the plot, or slightly off it to the edge as well.如前所述,您还可以将图例放在图中,或者也可以稍微放在边缘。 Here is an example using the Plotly Python API , made with an IPython Notebook .下面是一个使用Plotly Python API的例子,它是用IPython Notebook 制作的 I'm on the team.我在队里。

To begin, you'll want to install the necessary packages:首先,您需要安装必要的软件包:

import plotly
import math
import random
import numpy as np

Then, install Plotly:然后,安装 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)

This creates your graph, and allows you a chance to keep the legend within the plot itself.这将创建您的图表,并让您有机会将图例保留在绘图本身中。 The default for the legend if it is not set is to place it in the plot, as shown here.如果未设置图例,则默认将其放置在图中,如下所示。

在此处输入图片说明

For an alternative placement, you can closely align the edge of the graph and border of the legend, and remove border lines for a closer fit.对于替代放置,您可以将图形的边缘和图例的边框紧密对齐,并移除边框线以更贴合。

在此处输入图片说明

You can move and re-style the legend and graph with code, or with the GUI.您可以使用代码或 GUI 移动和重新设置图例和图形的样式。 To shift the legend, you have the following options to position the legend inside the graph by assigning x and y values of <= 1. Eg :要移动图例,您可以使用以下选项通过分配 <= 1 的 x 和 y 值来将图例定位在图形内。例如:

  • {"x" : 0,"y" : 0} -- Bottom Left {"x" : 0,"y" : 0} -- 左下角
  • {"x" : 1, "y" : 0} -- Bottom Right {"x" : 1, "y" : 0} -- 右下角
  • {"x" : 1, "y" : 1} -- Top Right {"x" : 1, "y" : 1} -- 右上角
  • {"x" : 0, "y" : 1} -- Top Left {"x" : 0, "y" : 1} -- 左上角
  • {"x" :.5, "y" : 0} -- Bottom Center {"x" :.5, "y" : 0} -- 底部中心
  • {"x": .5, "y" : 1} -- Top Center {"x": .5, "y" : 1} -- 顶部中心

In this case, we choose the upper right, legendstyle = {"x" : 1, "y" : 1} , also described in the documentation :在这种情况下,我们选择右上角, legendstyle = {"x" : 1, "y" : 1}文档中也有描述:

在此处输入图片说明

It's worth refreshing this question, as newer versions of Matplotlib have made it much easier to position the legend outside the plot.值得刷新这个问题,因为新版本的 Matplotlib 使得将图例定位在情节之外变得更加容易。 I produced this example with Matplotlib version 3.1.1 .我用 Matplotlib 版本3.1.1制作了这个例子。

Users can pass a 2-tuple of coordinates to the loc parameter to position the legend anywhere in the bounding box.用户可以将坐标的 2 元组传递给loc参数,以将图例定位在边界框中的任何位置。 The only gotcha is you need to run plt.tight_layout() to get matplotlib to recompute the plot dimensions so the legend is visible:唯一的问题是您需要运行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()

This leads to the following plot:这导致了以下情节:

外面有图例的情节

References:参考:

I simply used the string 'center left' for the location, like in matlab.我只是使用字符串'center left'作为位置,就像在 matlab 中一样。 I imported pylab from matplotlib.我从 matplotlib 导入了 pylab。

see the code as follow:看代码如下:

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(loc='center left', bbox_to_anchor=(1, 0.5),fancybox = True, shadow = True)

在此处输入图片说明

Something along these lines worked for me.沿着这些路线的东西对我有用。 Starting with a bit of code taken from Joe, this method modifies the window width to automatically fit a legend to the right of the figure.从 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()

The solution that worked for me when I had huge legend was to use extra empty image layout.当我有巨大的传奇时,对我有用的解决方案是使用额外的空图像布局。 In following example I made 4 rows and at the bottom I plot image with offset for legend (bbox_to_anchor) at the top it does not get cut.在下面的示例中,我制作了 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')

Here's another solution, similar to adding bbox_extra_artists and bbox_inches , where you don't have to have your extra artists in the scope of your savefig call.这是另一种解决方案,类似于添加bbox_extra_artistsbbox_inches ,您不必在savefig调用范围内添加额外的艺术家。 I came up with this since I generate most of my plot inside functions.我想出了这个,因为我在函数内部生成了大部分情节。

Instead of adding all your additions to the bounding box when you want to write it out, you can add them ahead of time to the Figure 's artists.当您想写出边界框时,无需将所有添加项添加到边界框,而是可以提前将它们添加到Figure的艺术家。 Using something similar to Franck Dernoncourt's answer above :使用类似于上面Franck Dernoncourt 的回答的内容

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

Here's the generated plot.这是生成的情节。

You can also try figlegend .您也可以尝试figlegend It is possible to create a legend independent of any Axes object.可以创建独立于任何 Axes 对象的图例。 However, you may need to create some "dummy" Paths to make sure the formatting for the objects gets passed on correctly.但是,您可能需要创建一些“虚拟”路径以确保对象的格式正确传递。

Here is an example from the matplotlib tutorial found here .这是来自此处的 matplotlib 教程的示例。 This is one of the more simpler examples but I added transparency to the legend and added plt.show() so you can paste this into the interactive shell and get a result:这是更简单的示例之一,但我为图例添加了透明度并添加了 plt.show() 以便您可以将其粘贴到交互式 shell 中并获得结果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM