Python 如何定位和对齐matplotlib地物图例?

Python 如何定位和对齐matplotlib地物图例?,python,matplotlib,legend,Python,Matplotlib,Legend,我有一个图,有两个子图,两行一列。我可以添加一个漂亮的人物图例 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((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指定图例框的左边缘/角,而不是中心。我搜索了align、horizontallignment等关键词,但没有找到。我还尝试获取“图例位置”,但图例没有*get_position()*方法。我读过关于*bbox_to_anchor*的文章,但当应用到人物图例时,我无法理解它。这似乎是为轴图例制作的

或者:我应该使用移位轴图例吗?但是,为什么首先会有人物传说呢?无论如何,必须能够“居中对齐”图形图例,因为loc=“lower center”也可以这样做

谢谢你的帮助


Martin

在这种情况下,您可以将轴用于figure
legend
方法。在这两种情况下,
bbox\u to\u anchor
是关键。正如您已经注意到的那样,
bbox\u to\u anchor
指定一个坐标元组(或一个框)来放置图例。使用
bbox\u to\u锚定时
位置
kwarg视为控制水平和垂直对齐

区别在于坐标元组是被解释为轴坐标还是图形坐标

作为使用地物图例的示例:

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

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

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

这是一个非常好的问题,公认的答案表示键(即
loc
表示对齐,
bbox\u to\u锚
表示位置)。我还尝试了一些代码,并想强调
bbox\u transform
属性的重要性,这些属性有时可能需要明确指定才能达到预期效果。下面我将向您展示我在
fig.legend
上的发现<代码>轴。图例应与
loc
非常相似,并且
bbox\u to\u锚定
的工作方式相同

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

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

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的x轴标签重叠。当图形的
figsize
和/或
dpi
发生变化时,这一问题将变得更加严重,请参见下文

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

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位数的
bbox\u-to\u-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\u变换
明确地告知为
fig.transFigure
。这是可以理解的,因为大多数时候我们将使用
ax.legend()

作为替代方案,我们还可以为
loc
使用4号样式
bbox\u to\u锚定。这实质上是为图例指定一个实框,
loc
表示对齐!默认的
bbox\u to\u锚定
应该是
[0,0,1,1]
,这意味着整个图形框!这四个数字分别代表x0、y0、宽度和高度。它非常类似于!因此,您可以轻松地更改
y0
,使其略低于
axbox.y0
,并相应地调整
loc

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)


谢谢你,乔。这是澄清。经过进一步思考,我想我的原始问题的答案应该是:“如果你想使用轴坐标,请使用axes.legend。”然而,出于好奇,我仍然想知道loc关键字是否是控制图例框中文本对齐的唯一方法?在许多其他matplotlib对象中,可以提取面片、线等(例如,请参见boxplot文档),并修改其特性。这似乎不适用于(图例中的文本对象),至少不直接适用。我说得对吗?