Python Matplotlib 外图自动图例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30413789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:24:28  来源:igfitidea点击:

Matplotlib automatic legend outside plot

pythonmatplotlibplotlegendlegend-properties

提问by edesz

I am trying to use the keyword bbox_to_anchor()in a matplotlib plot in Python.

我试图bbox_to_anchor()在 Python 的 matplotlib 图中使用关键字。

Here is a very basic plot that I have produced:

这是我制作的一个非常基本的情节:

import matplotlib.pyplot as plt
x = [1,2,3]
plt.subplot(211)
plt.plot(x, label="test1")
plt.plot([3,2,1], label="test2")
plt.legend(bbox_to_anchor=(0, -0.15, 1, 0), loc=2, ncol=2, mode="expand", borderaxespad=0)
plt.show()

It is based on the example here: http://matplotlib.org/users/legend_guide.html#plotting-guide-legend

它基于这里的示例:http: //matplotlib.org/users/legend_guide.html#plotting-guide-legend

I am trying to automatically place the legend outside the plot using bbox_to_anchor(). In this example, bbox_to_anchor()has 4 arguments listed.

我正在尝试使用bbox_to_anchor(). 在此示例中,bbox_to_anchor()列出了 4 个参数。

In this particular example (above), the legend is placed below the plot so the number -0.15 needs to be manually entered each time a plot is changed (font size, axis title removed, etc.). Is it possible to automatically calculate these 4 numbers for the following scenarios?:

在此特定示例(上图)中,图例位于图下方,因此每次更改图(字体大小、删除轴标题等)时都需要手动输入数字 -0.15。 是否可以针对以下场景自动计算这 4 个数字?

  1. legend below plot
  2. legend above plot
  3. legend to right of plot
  1. 图下方的图例
  2. 图上方的图例
  3. 情节右侧的图例

If not, is it possible to make good guesses about these numbers, in Python?

如果没有,是否有可能在 Python 中对这些数字做出很好的猜测?

Also, in the example code above I have set the last 2 numbers in bbox_to_anchor()to 1 and 0 since I do not understand what they are or how they work. What do the last 2 numbers in bbox_to_anchor()mean?

另外,在上面的示例代码中,我将最后 2 个数字设置bbox_to_anchor()为 1 和 0,因为我不明白它们是什么或它们是如何工作的。最后两个数字bbox_to_anchor()是什么意思?

采纳答案by Moritz

EDIT:

编辑:

I HIGHLY RECOMMEND USING THE ANSWER FROM ImportanceOfBeingErnest: How to put the legend out of the plot

我强烈建议使用来自ImportanceOfBeingErnest的答案: 如何将传奇排除在情节之外

This one is easier to understand:

这个比较容易理解:

import matplotlib.pyplot as plt
x = [1,2,3]
plt.subplot(211)
plt.plot(x, label="test1")
plt.plot([3,2,1], label="test2")
plt.legend(bbox_to_anchor=(0, 1), loc='upper left', ncol=1)
plt.show()

now play with the to coordinates (x,y). For locyou can use:

现在玩到坐标(x,y)。因为loc您可以使用:

valid locations are:
right
center left
upper right
lower right
best
center
lower left
center right
upper left
upper center
lower center

回答by Steve Horst

The argument to bbox_to_anchor is in Axes Coordinates. matplotlib uses different coordinate systems to ease placement of objects on the screen. When dealing with positioning legends, the critical coordinate systems to deal with are Axes coordinates, Figure coordinates, and Display coordinates (in pixels) as shown below:

bbox_to_anchor 的参数在轴坐标中。matplotlib 使用不同的坐标系来简化对象在屏幕上的放置。在处理定位图例时,要处理的关键坐标系是轴坐标、图形坐标和显示坐标(以像素为单位),如下所示:

matplotlib coordinate systems

matplotlib 坐标系

As previously mentioned, bbox_to_anchor is in Axes coordinates and does not require all 4 tuple arguments for a rectangle. You can simply give it a two-argument tuple containing (xpos, ypos) in Axes coordinates. The loc argument in this case will define the anchor point for the legend. So to pin the legend to the outer right of the axes and aligned with the top edge, you would issue the following:

如前所述, bbox_to_anchor 在 Axes 坐标中,不需要矩形的所有 4 个元组参数。您可以简单地在 Axes 坐标中给它一个包含 (xpos, ypos) 的双参数元组。这种情况下的 loc 参数将定义图例的锚点。因此,要将图例固定到轴的右外侧并与顶部边缘对齐,您将发出以下命令:

lgd = plt.legend(bbox_to_anchor=(1.01, 1), loc='upper left')

This however does not reposition the Axes with respect to the Figure and this will likely position the legend off of the Figure canvas. To automatically reposition the Figure canvas to align with the Axes and legend, I have used the following algorithm.

然而,这不会相对于图形重新定位轴,这可能会将图例定位在图形画布之外。为了自动重新定位图形画布以与轴和图例对齐,我使用了以下算法。

First, draw the legend on the canvas to assign it real pixel coordinates:

首先,在画布上绘制图例以为其分配实际像素坐标:

plt.gcf().canvas.draw()

Then define the transformation to go from pixel coordinates to Figure coordinates:

然后定义从像素坐标到图形坐标的转换:

invFigure = plt.gcf().transFigure.inverted()

Next, get the legend extents in pixels and convert to Figure coordinates. Pull out the farthest extent in the x direction since that is the canvas direction we need to adjust:

接下来,获取以像素为单位的图例范围并转换为图形坐标。在 x 方向拉出最远的范围,因为这是我们需要调整的画布方向:

lgd_pos = lgd.get_window_extent()
lgd_coord = invFigure.transform(lgd_pos)
lgd_xmax = lgd_coord[1, 0]

Do the same for the Axes:

对 Axes 执行相同操作:

ax_pos = plt.gca().get_window_extent()
ax_coord = invFigure.transform(ax_pos)
ax_xmax = ax_coord[1, 0]

Finally, adjust the Figure canvas using tight_layout for the proportion of the Axes that must move over to allow room for the legend to fit within the canvas:

最后,使用 tiny_layout 调整图形画布,调整必须移动的轴的比例,以便为图例留出适合画布的空间:

shift = 1 - (lgd_xmax - ax_xmax)
plt.gcf().tight_layout(rect=(0, 0, shift, 1))

Note that the rect argument to tight_layout is in Figure coordinates and defines the lower left and upper right corners of a rectangle containing the tight_layout bounds of the Axes, which does not include the legend. So a simple tight_layout call is equivalent to setting rect bounds of (0, 0, 1, 1).

请注意,tight_layout 的 rect 参数在 Figure 坐标中,并定义了包含 Axes 的 tiny_layout 边界的矩形的左下角和右上角,其中不包括图例。所以一个简单的tight_layout 调用相当于设置矩形边界为(0, 0, 1, 1)。