我有一个带有两个子图的图,分为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 指定图例框的左边/角,而不是中心。我搜索了诸如 align , horizontalalignment 等关键字,但找不到任何关键字。我也尝试获取“图例位置”,但是图例没有* get_position()*方法。我读到了关于* bbox_to_anchor *但是在应用于图形图例时无法理解它。这似乎是针对轴传说。
或者:我应该使用移位轴图例吗?但那么,为什么首先出现这样的传说呢?并且不知何故,必须能够“居中对齐”图形图例,因为 loc =“lower center”也是如此。
感谢您的帮助,
马丁
答案 0 :(得分:27)
在这种情况下,您可以将轴用于图legend
方法。在任何一种情况下,bbox_to_anchor
都是关键。正如您已经注意到bbox_to_anchor
指定了一个坐标元组(或一个框)来放置图例。当您使用bbox_to_anchor
时,请将location
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()
答案 1 :(得分:0)
这是一个非常好的问题,可接受的答案表示键(即loc
表示对齐,bbox_to_anchor
表示位置)。我还尝试了一些代码,并想强调 bbox_transform
属性的重要性,有时可能需要明确指定该属性以实现所需的效果。下面,我将向您展示我在fig.legend
上的发现。 ax.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)
这基本上是令人满意的。但是很容易发现图例覆盖了ax2
的x轴刻度标签。当图中的figsize
和/或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
与图例之间有很大的差距。那不是我们想要的。像发问者一样,我们想手动控制图例的位置。首先,我将像答案一样使用bbox_to_anchor
的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')
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
。 By default None, the Axes' transAxes transform will be used。这是可以理解的,因为在大多数情况下,我们将使用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_anchor
使用4位数样式loc
。这实际上是为图例指定一个真实的框,loc
实际上表示对齐!默认的bbox_to_anchor
应该只是[0,0,1,1]
,这意味着整个图形框!四个数字分别代表x0,y0,width,height
。它与specifying a cax for a shared colorbar非常相似!因此,您可以轻松地将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)