如何把这个传说排除在阴谋之外
我有一个系列的20个地块(不是小插曲)在一个单一的数字。 我希望传奇在盒子外面。 与此同时,我不想改变轴,随着数字的大小减less。 请帮助我以下查询:
- 我想保留graphics区域外的图例框。 (我想让传说在剧情区域的右侧)。
- 是否有减less图例框内的文字的字体大小,以使图例框的尺寸变小。
创build字体属性
from matplotlib.font_manager import FontProperties fontP = FontProperties() fontP.set_size('small') legend([plot1], "title", prop=fontP)
有很多方法可以做你想做的事情。 要添加@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()
如果我们做同样的事情,但是使用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()
同样的,你可以使图例更加水平和/或把它放在图的顶部(我也打开了圆angular和一个简单的阴影):
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()
或者,您可以缩小当前绘图的宽度,并将图例完全放在graphics的轴线之外:
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()
以类似的方式,您可以垂直缩小绘图,并将水平图例放在底部:
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图例指南 。 你也可以看看plt.figlegend()
。 希望有一点帮助!
放置图例( bbox_to_anchor
)
图例使用plt.legend
的loc
参数定位在轴的边界框内。
例如, loc="upper right"
将图例放置在边界框的右上angular,默认情况下,轴坐标( (0,0)
到(1,1)
(或边界框记号(x0,y0, width, height)=(0,0,1,1)
)。
要将图例置于坐标轴边界框之外,可以指定图例左下angular坐标的元组(x0,y0)
。
plt.legend(loc=(1.04,0))
然而,更通用的方法是使用bbox_to_anchor
参数手动指定放置图例的边界框。 可以限制自己只提供bbox的(x0,y0)
部分。 这将创build一个零跨度框,其中图例将按照loc
参数给出的方向展开。 例如
plt.legend(bbox_to_anchor =(1.04,1),loc =“左上angular”)
将图例置于轴的外部,使得图例的左上angular位于轴坐标中的位置(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")
有关如何解释bbox_to_anchor
的4元组参数的详细信息(如l4
)可以在此问题中find。 mode="expand"
在四元组给出的边界框内水平扩展图例。 对于垂直扩展的图例,请参阅此问题 。
有时可以在graphics坐标中指定边界框而不是坐标轴。 这在上面的示例l5
示出,其中bbox_transform
参数用于将图例置于图的左下angular。
后期处理
将图例置于斧头以外常常导致不希望的情况,即它完全或部分在graphicscanvas之外。
解决这个问题的方法是:
-
调整子图参数
我们可以通过plt.subplots_adjust调整子图参数,使得图中的轴占用更less的空间(从而为图例留下更多的空间)。 例如plt.subplots_adjust(right=0.7)
在图的右侧留下30%的空间,其中可以放置图例。
-
紧张的布局
使用plt.tight_layout
允许自动调整子图参数,使图中的元素与graphics边缘紧密alignment。 不幸的是,在这个自动机制中没有考虑到这个图例,但是我们可以提供一个矩形盒子来包含整个子图区域(包括标签)。plt.tight_layout(rect=[0,0,0.75,1])
-
用
bbox_inches = "tight"
保存图
对bbox_inches = "tight"
的参数bbox_inches = "tight"
可用于保存graphics,以使canvas上的所有艺术家(包括图例)都适合保存的区域。 如果需要,graphics尺寸会自动调整。plt.savefig("output.png", bbox_inches="tight")
- 自动调整子区域参数
在这个答案中可以find一种自动调整子图位置的方法,使得图例适合在canvas内而不改变graphics大小 : 创build具有精确大小和无填充的graphics(以及轴外的图例)
上面讨论的情况之间的比较:
备择scheme
使用bbox_to_anchor
的替代方法bbox_to_anchor
将图例置于其专用子图轴( lax
)中。 由于图gridspec_kw={"width_ratios":[4,1]}
图应该小于图,我们可以在创build坐标轴时使用gridspec_kw={"width_ratios":[4,1]}
。 我们可以隐藏坐标轴lax.axis("off")
但是仍然放入一个图例。图例句柄和标签需要通过h,l = ax.get_legend_handles_labels()
从真实的图中获得,然后可以提供给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 传说指南与其他东西你想要做的传说的一些例子。
- 用于放置饼图的图例的一些示例代码可以直接在这个问题的答案中find: Python – 图例与饼图重叠
-
loc
参数可以取数字而不是string,这样可以缩短调用时间,但是它们并不是很直观的映射到对方。 以下是供参考的映射:
如果你正在使用Pandas plot()
包装函数,并且想把外部的传说放在这里,那么这里很简单:
df.myCol.plot().legend(loc='center left', bbox_to_anchor=(1, 0.5))
我们只需在plot()
之后链接legend()
plot()
。
结果看起来像这样:
简短的回答:你可以使用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')
为了防止图例框被剪裁,保存graphics时,可以使用参数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])
简答 :在图例上调用draggable,然后交互式地将其移动到任意位置:
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()
除了这里所有的优秀答案之外,更新版本的matplotlib
和pylab
可以自动确定在哪里放置图例而不干扰地块 。
pylab.legend(loc='best')
这会自动将图例置于剧情之外!
要将图例置于绘图区域之外,请使用legend()的loc和bbox_to_anchor关键字。 例如,下面的代码将把图例放在绘图区的右边:
legend(loc="upper left", bbox_to_anchor=(1,1))
有关更多信息,请参阅图例指南
不完全是你所要求的,但我发现这是同样的问题的替代scheme。 使图例半透明,如下所示:
做到这一点:
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)
如上所述,您还可以将图例放置在图中,或稍微偏离边缘。 以下是使用IPython Notebook制作的Plotly Python API的示例。 我在队里。
首先,您需要安装必要的软件包:
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)^kx^{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)
这将创build您的graphics,并让您有机会将图例保留在绘图本身内。 如果未设置图例的默认值,则将其放置在图中,如下所示。
对于替代的放置,您可以将graphics的边缘和图例的边框紧密alignment,并删除边框线以便更贴合。
您可以使用代码或使用GUI移动和重新设置图例和graphics的样式。 要移动图例,您可以通过将<= 1的x和y值赋值给图例来定位图例。例如:
-
{"x" : 0,"y" : 0}
– 左下angular -
{"x" : 1, "y" : 0}
– 右下 -
{"x" : 1, "y" : 1}
– 右上angular -
{"x" : 0, "y" : 1}
– 左上angular -
{"x" :.5, "y" : 0}
– 底部中心 -
{"x": .5, "y" : 1}
– Top Center
在这种情况下,我们select右上angularlegendstyle = {"x" : 1, "y" : 1}
,在文档中也进行了描述:
沿着这些线路的东西为我工作。 从一些从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()
你也可以试试figlegend
。 可以创build独立于任何Axes对象的图例。 但是,您可能需要创build一些“虚拟”path,以确保对象的格式正确传递。
这里是matplotlib教程的例子。 这是更简单的例子之一,但我添加了透明度的图例,并添加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()
当我拥有巨大的传奇时,为我工作的解决scheme是使用额外的空白图像布局。 在下面的例子中,我做了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')
这是另一个解决scheme,类似于添加bbox_extra_artists
和bbox_inches
,您不必在savefig
调用的范围内添加额外的艺术家。 我想出了这个,因为我产生了大部分的function内的阴谋。
当你想把它写出来的时候,不要将所有的添加项加到边框上,而是提前将它们添加到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")
这是生成的情节。
不知道你是否已经解决了你的问题…可能是的,但是…我只是使用string“外部”的位置,就像在MATLAB中。 我从matplotlib中导入了pylab。 看代码如下:
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)
点击查看剧情