2017-10-12 122 views
3

我有一个图例,其图例固定在右上角:如何扩展图例以适合图表的高度?Matplotlib:垂直扩展图例

borderaxespad=0.会水平扩展它,但我找不到垂直扩展的等效项。

我使用matplotlib 2.0

示例代码:

import numpy as np 

x = np.linspace(0, 2*np.pi, 100) 
data = [np.sin(x * np.pi/float(el)) for el in range(1, 5)] 

fig, ax = plt.subplots(1) 
for key, el in enumerate(data): 
    ax.plot(x, el, label=str(key)) 
ax.legend(bbox_to_anchor=(1.04,1), loc="upper left", borderaxespad=0., mode='expand') 
plt.tight_layout(rect=[0,0,0.8,1]) 

主要生产:

enter image description here

回答

1

首先解释从提问的输出:当使用2元组表示法为bbox_to_anchor,创建不程度的边界框。 mode="expand"会将图例水平扩展到该边界框,该边界框具有零延伸,有效地将其缩小到零大小。

问题是mode="expand"只会水平扩展图例。 从the documentation

mode:{“扩大”,无}
如果模式被设置为“扩展”的说明将是水平膨胀以填充所述轴区域(或bbox_to_anchor如果定义了传说的大小)。

对于需要深入挖掘图例内部的解决方案。首先,您需要使用4元组来设置bbox-to-anchor,并指定bbox的宽度和高度,bbox_to_anchor=(x0,y0,width,height),其中所有数字都在规范化的坐标轴中。然后你需要计算图例的_legend_box的高度。由于设置了一些填充,因此您需要从边界框的高度中减去填充。为了计算填充,必须知道当前图例的字体大小。所有这些都必须在轴的位置最后更改后进行。

import matplotlib.pyplot as plt 
import numpy as np 

x = np.linspace(0, 2*np.pi, 100) 
data = [np.sin(x * np.pi/float(el)) for el in range(1, 5)] 

fig, ax = plt.subplots(1) 
for key, el in enumerate(data): 
    ax.plot(x, el, label=str(key)) 

# legend:  
leg = ax.legend(bbox_to_anchor=(1.04,0.0,0.2,1), loc="lower left", 
       borderaxespad=0, mode='expand') 

plt.tight_layout(rect=[0,0,0.8,1]) 

# do this after calling tight layout or changing axes positions in any way: 
fontsize = fig.canvas.get_renderer().points_to_pixels(leg._fontsize) 
pad = 2 * (leg.borderaxespad + leg.borderpad) * fontsize 
leg._legend_box.set_height(leg.get_bbox_to_anchor().height-pad) 

plt.show() 

enter image description here

+0

谢谢,这是一个伟大的答案。 你认为这是值得把这个功能请求标记为matplotlib吗?我没有看到水平/垂直传奇之间不对称的原因。 另外,如何将标签间距的@jrjc建议整合到图例中以均匀分布标签? – FLab

+0

我想可以加入这个matplotlib,使用像'mode =“expandboth”'等新标志。问题将是结果应该是什么样子。如上所述,留下很多空白空间?或者垂直分配手柄,从而覆盖设置的标签间距?目前,我对创建图例后如何设置标签间距没有任何想法。我可能会在某个时候考虑这个问题,但不是我想的那么快。 – ImportanceOfBeingErnest

1

labelspacing可能是你找什么呢?

fig, ax = plt.subplots(1) 
for key, el in enumerate(data): 
    ax.plot(x, el, label=str(key)) 
ax.legend(labelspacing=8, loc=6, bbox_to_anchor=(1, 0.5)) 
plt.tight_layout(rect=[0, 0, 0.9, 1]) 

它不是自动的,但你可能会发现一些关系figsize(这也是8这里)。

loc=6, bbox_to_anchor=(1, 0.5)将以你的图例右侧为中心。

其中给出: expand legend matplotib