26

我有一个带有两个子图的图形,分别为 2 行和 1 列。我可以添加一个漂亮的人物图例

fig.legend((l1, l2), ['2011', '2012'], loc="lower center", 
           ncol=2, fancybox=True, shadow=True, prop={'size':'small'})

但是,这个图例位于图形的中心,而不是我想要的中心下方。现在,我可以获得我的坐标轴坐标

axbox = ax[1].get_position()

理论上我应该能够通过使用元组指定loc关键字来定位图例:

fig.legend(..., loc=(axbox.x0+0.5*axbox.width, axbox.y0-0.08), ...)

这有效,除了图例左对齐,以便loc指定图例框的左边缘/角而不是中心。我搜索了诸如alignHorizo ​​ntalalignment等关键字,但没有找到。我也尝试获取“图例位置”,但图例没有 *get_position()* 方法。我读到了 *bbox_to_anchor* 但在应用于图形图例时无法理解。这似乎是为轴传奇制作的。

或者:我应该改用移位轴图例吗?但是,为什么首先会有人物传说呢?并且以某种方式必须可以“居中对齐”图形图例,因为loc="lower center"也可以。

谢谢你的帮助,

马丁

4

2 回答 2

34

在这种情况下,您可以将轴用于图形legend方法。无论哪种情况,bbox_to_anchor都是关键。正如您已经注意到的那样bbox_to_anchor,指定了一个坐标元组(或一个框)来放置图例。当您使用bbox_to_anchor时,将locationkwarg 视为控制水平和垂直对齐。

区别只是坐标元组是被解释为轴还是图形坐标。

作为使用图形图例的示例:

import numpy as np
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)

x = np.linspace(0, np.pi, 100)

line1, = ax1.plot(x, np.cos(3*x), color='red')
line2, = ax2.plot(x, np.sin(4*x), color='green')

# The key to the position is bbox_to_anchor: Place it at x=0.5, y=0.5
# in figure coordinates.
# "center" is basically saying center horizontal alignment and 
# center vertical alignment in this case
fig.legend([line1, line2], ['yep', 'nope'], bbox_to_anchor=[0.5, 0.5], 
           loc='center', ncol=2)

plt.show()

在此处输入图像描述

作为使用轴方法的示例,请尝试以下操作:

import numpy as np
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)

x = np.linspace(0, np.pi, 100)

line1, = ax1.plot(x, np.cos(3*x), color='red')
line2, = ax2.plot(x, np.sin(4*x), color='green')

# The key to the position is bbox_to_anchor: Place it at x=0.5, y=0
# in axes coordinates.
# "upper center" is basically saying center horizontal alignment and 
# top vertical alignment in this case
ax1.legend([line1, line2], ['yep', 'nope'], bbox_to_anchor=[0.5, 0], 
           loc='upper center', ncol=2, borderaxespad=0.25)

plt.show()

在此处输入图像描述

于 2012-12-19T23:06:46.893 回答
4

这是一个很好的问题,接受的答案表明了关键(即loc表示对齐和bbox_to_anchor表示位置)。我也尝试了一些代码,并想强调有时需要明确指定才能达到预期效果的属性的重要性。bbox_transform下面我将向您展示我的发现fig.legendax.legend应该非常相似,loc并且bbox_to_anchor工作方式相同。

使用默认设置时,我们将有以下内容。

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(6,4), sharex=True)

x = np.linspace(0, np.pi, 100)
line1, = ax1.plot(x, np.cos(3*x), color='red')
line2, = ax2.plot(x, np.sin(4*x), color='green')

fig.legend([line1, line2], ['yep', 'nope'], loc='lower center', ncol=2)

在此处输入图像描述

这基本上是令人满意的。但很容易发现,图例与 .x 轴刻度标签重叠ax2figsize当和/或dpi图形发生变化时,这个问题将变得更加严重,请参见下文。

fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(6,12), sharex=True, facecolor='w', gridspec_kw={'hspace':0.01})

x = np.linspace(0, np.pi, 100)
line1, = ax1.plot(x, np.cos(3*x), color='red')
line2, = ax2.plot(x, np.sin(4*x), color='green')

fig.legend([line1, line2], ['yep', 'nope'], loc='lower center', ncol=2)

在此处输入图像描述

ax2所以你看到和传说之间有很大的差距。这不是我们想要的。像提问者一样,我们想手动控制图例的位置。首先,我将使用 2-number 样式,bbox_to_anchor就像答案一样。

fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(6,12), sharex=True, facecolor='w', gridspec_kw={'hspace':0.01})

x = np.linspace(0, np.pi, 100)
line1, = ax1.plot(x, np.cos(3*x), color='red')
line2, = ax2.plot(x, np.sin(4*x), color='green')

axbox = ax2.get_position()

# to place center point of the legend specified by loc at the position specified by bbox_to_anchor.
fig.legend([line1, line2], ['yep', 'nope'], loc='center', ncol=2,
           bbox_to_anchor=[axbox.x0+0.5*axbox.width, axbox.y0-0.05])

在此处输入图像描述

差不多好了!但这是完全错误的,因为传说的中心并不是我们真正意思的中心!解决这个问题的关键是我们需要明确告知bbox_transformas fig.transFigure默认情况下无,将使用轴的 transAxes 变换。这是可以理解的,因为我们大部分时间都会使用ax.legend().

fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(6,12), sharex=True, facecolor='w', gridspec_kw={'hspace':0.01})

x = np.linspace(0, np.pi, 100)
line1, = ax1.plot(x, np.cos(3*x), color='red')
line2, = ax2.plot(x, np.sin(4*x), color='green')

axbox = ax2.get_position()

# to place center point of the legend specified by loc at the position specified by bbox_to_anchor!
fig.legend([line1, line2], ['yep', 'nope'], loc='center', ncol=2,
           bbox_to_anchor=[axbox.x0+0.5*axbox.width, axbox.y0-0.05], bbox_transform=fig.transFigure)

在此处输入图像描述

作为替代方案,我们也可以bbox_to_anchorloc. 这本质上是为图例指定一个真实的框,并且loc真正表示对齐!默认bbox_to_anchor应该只是[0,0,1,1],意思是整个图形框!四个数字x0,y0,width,height分别代表 。这与为共享颜色条指定 cax非常相似!因此,您可以轻松地更改y0稍微低于axbox.y0loc进行相应调整。

fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(6,12), sharex=True, facecolor='w', gridspec_kw={'hspace':0.01})

x = np.linspace(0, np.pi, 100)
line1, = ax1.plot(x, np.cos(3*x), color='red')
line2, = ax2.plot(x, np.sin(4*x), color='green')

axbox = ax2.get_position()

# to place center point specified by loc at the position specified by bbox_to_anchor!
fig.legend([line1, line2], ['yep', 'nope'], loc='lower center', ncol=2,
           bbox_to_anchor=[0, axbox.y0-0.05,1,1], bbox_transform=fig.transFigure)

在此处输入图像描述

于 2020-04-04T10:07:15.537 回答