Matplotlib自动图例外图[重复]
Posted
技术标签:
【中文标题】Matplotlib自动图例外图[重复]【英文标题】:Matplotlib automatic legend outside plot [duplicate] 【发布时间】:2015-08-05 11:38:52 【问题描述】:我正在尝试在 Python 的 matplotlib 图中使用关键字 bbox_to_anchor()
。
这是我制作的一个非常基本的情节based on this example。 :
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()
我正在尝试使用bbox_to_anchor()
自动将图例放置在绘图之外。在此示例中,bbox_to_anchor()
列出了 4 个参数。
在这个特定的示例(上图)中,图例位于绘图下方,因此每次更改绘图时都需要手动输入数字 -0.15(字体大小、删除轴标题等)。 是否可以针对以下场景自动计算这 4 个数字?:
-
下图传说
图例之上
情节右侧的图例
如果没有,是否可以在 Python 中对这些数字做出正确的猜测?
另外,在上面的示例代码中,我将bbox_to_anchor()
中的最后两个数字设置为 1 和 0,因为我不明白它们是什么或它们是如何工作的。 bbox_to_anchor()
中的最后 2 个数字是什么意思?
【问题讨论】:
【参考方案1】:编辑:
我强烈建议使用 ImportanceOfBeingErnest 的答案: How to put the legend out of the plot
这个比较容易理解:
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()
现在使用 to 坐标 (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
【讨论】:
谢谢。不是每次都需要手动设置坐标吗? 另外,数据序列标签对我来说很长。在传说中,这导致它们被切断。有没有办法避免这种情况? 如果您设置“左上角”,例如 (1,1.25),则图例不在情节范围内。无论如何,图例应该很短【参考方案2】:bbox_to_anchor 的参数在轴坐标中。 matplotlib 使用不同的坐标系来简化屏幕上对象的放置。在处理定位图例时,要处理的关键坐标系是 Axes 坐标、Figure 坐标和 Display 坐标(以像素为单位),如下所示:
matplotlib coordinate systems
如前所述,bbox_to_anchor 位于 Axes 坐标中,并且不需要矩形的所有 4 个元组参数。您可以简单地给它一个包含 (xpos, ypos) 轴坐标的双参数元组。在这种情况下, loc 参数将定义图例的锚点。因此,要将图例固定在轴的右外侧并与顶部边缘对齐,您将发出以下命令:
lgd = plt.legend(bbox_to_anchor=(1.01, 1), loc='upper left')
但是,这不会重新定位 Axes 相对于 Figure 的位置,这可能会将图例定位在 Figure 画布之外。为了自动重新定位图形画布以与轴和图例对齐,我使用了以下算法。
首先,在画布上绘制图例,为其分配真实的像素坐标:
plt.gcf().canvas.draw()
然后定义从像素坐标到图形坐标的转换:
invFigure = plt.gcf().transFigure.inverted()
接下来,获取以像素为单位的图例范围并转换为图形坐标。拉出x方向最远的范围,因为那是我们需要调整的画布方向:
lgd_pos = lgd.get_window_extent()
lgd_coord = invFigure.transform(lgd_pos)
lgd_xmax = lgd_coord[1, 0]
对轴做同样的事情:
ax_pos = plt.gca().get_window_extent()
ax_coord = invFigure.transform(ax_pos)
ax_xmax = ax_coord[1, 0]
最后,使用tight_layout 调整图形画布,以调整必须移动的轴的比例,以便为图例留出空间以适应画布:
shift = 1 - (lgd_xmax - ax_xmax)
plt.gcf().tight_layout(rect=(0, 0, shift, 1))
请注意,tight_layout 的 rect 参数位于图形坐标中,并定义了包含轴的紧密布局边界的矩形的左下角和右上角,其中不包括图例。所以一个简单的tight_layout调用就相当于设置了(0, 0, 1, 1)的rect bounds。
【讨论】:
这是一个很好的答案。这是我尝试过的唯一一个以编程方式工作的。很好地解释了它;例如,如果将图例放在图的上方/下方,最好有一个更通用的答案,该答案可以向任何方向移动。 我喜欢你提供的坐标图。非常直观。以上是关于Matplotlib自动图例外图[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Py之matplotlib:matplotlib库图表绘制中常规设置大全(交互模式清除原有图像设置横坐标显示文字/旋转角度添加图例绘图布局自动调整图像显示图像暂停)