How to put the legend out of the plot
我有一系列20个图(不是子图),用一个数字绘制。我想让这个传说在盒子外面。同时,我不想更改轴,因为图形的大小会减小。如有以下问题,请帮助我:
有很多方法可以满足你的需要。要添加@inalis和@navi已经说过的内容,可以使用
在考虑减小字体大小(这会使内容难以阅读)之前,请尝试在不同的位置放置图例:
那么,让我们从一个通用示例开始:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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() |
如果我们做同样的事情,但是使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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() |
类似地,您可以使图例更水平和/或放在图形的顶部(我还打开圆角和简单的阴影):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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() |
或者,您可以缩小当前绘图的宽度,并将图例完全置于图形的轴之外:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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() |
以类似的方式,您可以垂直缩小绘图,并在底部放置水平图例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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() |
看看Matplotlib传奇指南。你也可以看看
(
传奇是一bounding放置盒的内侧轴对
在对轴的地方传说的bounding盒,一个元组可以指定坐标轴的
1 | plt.legend(loc=(1.04,0)) |
然而,更多的通用方法是手动指定的bounding箱应放置到它的传说,
1 | plt.legend(bbox_to_anchor=(1.04,1), loc="upper left") |
传说的地方超出了轴,这样,左上角的位置是在
在进一步的给出了一些例子,以及如何在不同的参数之间的
1 2 3 4 5 6 7 8 | 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") |
详细信息关于如何解释的问题
有时,它可能是有用的到指定的信箱中bounding坐标轴坐标图来代替。这是显示在上面的例子中
postprocessing
有传说,往往超出了观察到的情况undesired导联轴,这是完全的或局部的出现在画布上。
解决方案:这是问题
-
在subplot参数调整一个可以调整的参数,如subplot空间轴,以不出现(与内侧,从而把更多的空间利用到
plt.subplots_adjust 传奇)。例如1plt.subplots_adjust(right=0.7)叶片的空间在30%右手侧的数字,可以在一个地方的传说。
-
密封布置自动调整到
plt.tight_layout 允许使用的参数,如subplot元素在图对图的边坐着别动。不幸的是,传说是不考虑在这个自动的,但我们可以供应整个区的矩形框,将subplots(包括标签)插入安装。1plt.tight_layout(rect=[0,0,0.75,1]) -
《节能与
bbox_inches ="tight" 身材该参数可以用来对plt.savefig bbox_inches ="tight" 拯救所有的艺术家出现在画布上,这样的安装(包括传奇)是为保存地区。如果需要,该图是自动调整大小。1plt.savefig("output.png", bbox_inches="tight") - 自动调整子批次参数在这个答案中可以找到一种自动调整子批次位置的方法,使图例适合画布而不更改图形大小:创建具有精确大小且无填充的图形(以及轴外的图例)。
上述案例的比较:好的。
好的。选择
人物传说人们可以在图形中使用图例,而不是轴,
1 | fig.legend(loc=7) |
为人物不同轴上的所有艺术家创建一个图例。图例使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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() |
好的。
专用子批次轴内的图例使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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() |
这将生成一个与上面的绘图在视觉上非常相似的绘图:好的。
好的。
我们也可以使用第一个轴放置图例,但使用图例轴的
1 2 | ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes) lax.axis("off") |
在这种方法中,我们不需要从外部获取图例句柄,但需要指定
- 考虑Matplotlib Legend指南,其中包含一些您想用Legends处理的其他内容的示例。
- 一些用于放置饼图图例的示例代码可以直接在这个问题的答案中找到:python-图例与饼图重叠
loc 参数可以采用数字而不是字符串,这会缩短调用时间,但是它们之间的映射并不十分直观。以下是供参考的映射:
好的。好啊。
在
1 2 3 4 5 6 | # 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)) |
结果如下:
创建字体属性
1 2 3 4 5 | from matplotlib.font_manager import FontProperties fontP = FontProperties() fontP.set_size('small') legend([plot1],"title", prop=fontP) |
简单回答:您可以使用
更长的答案:您可以使用
但是,通常的问题是图例框被裁剪,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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') |
为了防止图例框被裁剪,保存图形时,可以使用参数
示例(我只更改了最后一行以向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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那样在本地允许图例框的外部位置:
1 2 3 4 5 6 7 | 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]) |
要将图例放置在绘图区域之外,请使用
1 | legend(loc="upper left", bbox_to_anchor=(1,1)) |
有关详细信息,请参阅图例指南
简短回答:在图例上调用Draggable,并将其交互移动到所需的任何位置:
1 | ax.legend().draggable() |
长答案:如果您更喜欢以交互方式/手动方式而不是以编程方式放置图例,则可以切换图例的可拖动模式,以便将其拖动到所需的任何位置。请检查以下示例:
1 2 3 4 5 6 7 8 9 10 11 | 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() |
除了这里所有优秀的答案,如果可能的话,新版的
1 | pylab.legend(loc='best') |
如果可能,这将自动将图例放在远离数据的位置!
但是,如果没有地方可以在不重叠数据的情况下放置图例,那么您将希望尝试其他答案之一;使用
不完全是你要求的,但我发现这是同一问题的另一种选择。把传说变成半超现实主义,就像这样:
这样做:
1 2 3 4 5 6 7 8 9 10 11 | 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) |
如前所述,您也可以将图例放置在绘图中,或者稍微偏离到边缘。下面是一个使用plotly python api的例子,它是用ipython笔记本制作的。我是团队成员。
首先,您需要安装必要的软件包:
1 2 3 4 | import plotly import math import random import numpy as np |
然后,按顺序安装:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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) |
这将创建图形,并允许您将图例保留在绘图本身中。如果没有设置,图例的默认设置是将其放置在绘图中,如图所示。
对于另一种放置方式,可以将图形的边缘与图例的边框紧密对齐,并删除边框线以获得更紧密的配合。
您可以使用代码或GUI移动和重新设置图例和图形的样式。要移动图例,可以通过指定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} —上中
在这种情况下,我们选择右上角的
沿着这条线的一些东西对我有用。从Joe获取的一点代码开始,此方法修改窗口宽度,使其自动适应图形右侧的图例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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() |
你也可以试试
当我有一个巨大的传奇时,我的解决方案是使用额外的空图像布局。在下面的示例中,我画了4行,在底部,我用偏移量为顶部的图例(bbox_to_anchor)绘制图像,它不会被剪切。
1 2 3 4 5 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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") |
这是生成的图。
下面是Matplotlib教程中的一个示例。这是一个更简单的例子,但我增加了图例的透明度,并添加了plt.show(),这样您就可以将其粘贴到交互式shell中并得到一个结果:
1 2 3 4 5 6 | 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() |
不知道你是否已经解决了你的问题…可能是的,但是…我只是使用字符串"outside"作为位置,就像在matlab中一样。我从Matplotlib进口了Pylab。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) |
点击查看绘图