【问题标题】:How to specify legend position in matplotlib in graph coordinates如何在图坐标中指定matplotlib中的图例位置
【发布时间】:2017-06-07 12:44:52
【问题描述】:

我知道 bbox_to_anchor 关键字和这个线程,它非常有帮助地建议如何手动放置图例:

How to put the legend out of the plot

但是,我想使用图表中 x 轴和 y 轴的坐标来指定图例位置(在图表内),因为我可能需要将图形移动到具有不同轴环境,并且我不想每次执行此操作时都手动使用这些坐标。这可能吗?

编辑:这里有一个小例子:

import numpy as n
f, axarr = plt.subplots(2,sharex=True)
axarr[1].set_ylim([0.611,0.675])
axarr[0].set_ylim([0.792,0.856]) 
axarr[0].plot([0, 0.04, 0.08],n.array([ 0.83333333,  0.82250521,0.81109048]), label='test1') 
axarr[0].errorbar([0, 0.04, 0.08],n.array([ 0.8,  0.83,   0.82]),n.array([0.1,0.1,0.01]), label='test2') 
axarr[1].plot([0, 0.04, 0.08],n.array([ 0.66666667,  0.64888304,  0.63042428]))
axarr[1].errorbar([0, 0.04, 0.08],n.array([ 0.67,  0.64,  0.62]),n.array([ 0.01,  0.05,  0.1]))
axarr[0].legend(bbox_to_anchor=(0.04, 0.82, 1., .102),labelspacing=0.1,       handlelength=0.1, handletextpad=0.1,frameon=False, ncol=4, columnspacing=0.7)

我认为让我感到困惑的是图例实际上并不是从 0.82 开始的,实际上对于我更大的图(有 5 个这种类型的子图),我需要使用图例坐标 bbox_to_anchor=(0.04, 1.15, 1., .102) 以使图例出现在坐标 (0.02, 0.83) 上。但也许我还有其他问题?

【问题讨论】:

  • 它并不清楚链接问题的解决方案对您有多大帮助,因为默认情况下 bbox_to_anchor 参数采用轴坐标,就像您希望的那样。您可能想举例说明您正在努力实现的目标和/或更好地说明解决方案与您所寻找的不符的程度。
  • 谢谢 - 我已经编辑过了。但也许你是对的,我只是误解了 matplotlib 通常如何放置这些图例 - 你知道图例的哪个角放置在 bbox_to_anchor 的坐标上吗?
  • 好吧,我以为我对my answer to the linked question 有一个完整的解释。还包含指向 this question 的链接,其中显示了如何解释 4 元组 bbox_to_anchor 规范。我可能仍会尝试在这里回答您的问题,但为此,我需要知道您在询问“图例出现在坐标(0.02,0.83)上时的确切含义”是您想要的左下角吗?
  • 抱歉,我以为我已经仔细查看了另一篇帖子,但我没有向下滚动足够远来查看您的答案 - 谢谢,现在试图理解这一点。是的,我确实想在这些坐标处左下角。
  • 好吧,抱歉,只是为了检查一下我是否正确:所以当我只说 loc="upper right" 并且没有给出 bbox_to_anchor 规范时,matplotlib 将其解释为相对于轴的 loc。但是当我说 loc="upper right" 并给出 bbox_to_anchor 规范时,该 bbox_to_anchor 规范将相对于轴进行解释,而 loc 关键字指的是图例的角?

标签: python matplotlib


【解决方案1】:

loc 参数指定图例放置在边界框的哪个角。 loc 的默认值是 loc="best",当使用 bbox_to_anchor 参数时会产生不可预测的结果。
因此,在指定 bbox_to_anchor 时,总是同时指定 loc

bbox_to_anchor 的默认值为 (0,0,1,1),它是整个坐标区上的边界框。如果指定了不同的边界框,通常使用前两个值就足够了,它们给出了边界框的 (x0, y0)。

下面是一个示例,其中边界框设置为位置(0.6,0.5)(绿点)并测试了不同的loc参数。因为图例超出边界框,loc 参数可以解释为“图例的哪个角应放置在 2 元组 bbox_to_anchor 参数给定的位置”。

import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6, 3
fig, axes = plt.subplots(ncols=3)
locs = ["upper left", "lower left", "center right"]
for l, ax in zip(locs, axes.flatten()):
    ax.set_title(l)
    ax.plot([1,2,3],[2,3,1], "b-", label="blue")
    ax.plot([1,2,3],[1,2,1], "r-", label="red")
    ax.legend(loc=l, bbox_to_anchor=(0.6,0.5))
    ax.scatter((0.6),(0.5), s=81, c="limegreen", transform=ax.transAxes)

plt.tight_layout()    
plt.show()

详细解释见this answer,问题What does a 4-element tuple argument for 'bbox_to_anchor' mean in matplotlib?


如果要在坐标轴坐标以外的其他坐标中指定图例位置,可以使用 bbox_transform 参数来实现。如果使用图形坐标可能有意义
ax.legend(bbox_to_anchor=(1,0), loc="lower right",  bbox_transform=fig.transFigure)

使用数据坐标可能没有太大意义,但既然你要求它,这将通过bbox_transform=ax.transData 完成。

【讨论】:

    【解决方案2】:

    我经常使用的方式是图例函数中的 loc 参数。字符串输入效果很好:

    plt.legend(loc = "upper left")
    

    正如文档所说,对于字符串引用,您可以使用:

            ===============   =============
            Location String   Location Code
            ===============   =============
            'best'            0
            'upper right'     1
            'upper left'      2
            'lower left'      3
            'lower right'     4
            'right'           5
            'center left'     6
            'center right'    7
            'lower center'    8
            'upper center'    9
            'center'          10
            ===============   =============
    

    【讨论】:

      【解决方案3】:

      您可以使用 loc 参数更改图例的位置。 https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html?highlight=legend#matplotlib.axes.Axes.legend

      import matplotlib.pyplot as plt
      
      plt.subplot(211)
      plt.plot([1,2,3], label="test1")
      plt.plot([3,2,1], label="test2")
      # Place a legend above this subplot, expanding itself to
      # fully use the given bounding box.
      plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
                 ncol=2, mode="expand", borderaxespad=0.)
      
      plt.subplot(223)
      plt.plot([1,2,3], label="test1")
      plt.plot([3,2,1], label="test2")
      # Place a legend to the right of this smaller subplot.
      plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
      
      plt.show()
      

      【讨论】:

      • 对不起 - bbox_to_anchor 和 loc 关键字如何交互? bbox_to_anchor 会将图例放置在 loc 环境中的某个位置吗?
      • loc 参数将通知 matplotlib 图例边界框的哪一部分应该放在 bbox_to_anchor 的参数处。
      • @mzzx 如果您觉得这个答案有帮助(无论您是否接受),您仍然可以投票 - 这有点像说“谢谢”。
      【解决方案4】:

      根据matplotlib legend documentation

      位置也可以是 2 元组,以坐标轴坐标给出图例左下角的坐标(在这种情况下,bbox_to_anchor 将被忽略)。

      因此,可以使用:

      plt.legend(loc=(x, y))
      

      将图例的左下角设置为指定的(x, y) 位置。

      请注意,这里的xy 坐标是相对的,这意味着x=0 是图中最左边的点,x=1 是图中最右边的点。 y=0y=1 沿绘图高度也是如此。

      【讨论】:

        【解决方案5】:

        除了@ImportanceOfBeingErnest 的帖子之外,我还使用以下行在绘图中的绝对位置添加图例。

        plt.legend(bbox_to_anchor=(1.0,1.0),\
            bbox_transform=plt.gcf().transFigure)
        

        由于未知原因,bbox_transform=fig.transFigure 不适合我。

        【讨论】:

        • 这可能是因为你有不止一个数字。要选择当前图形,您可以使用plt.figure(fig.number),然后使用您的fig.transFigure 命令,它应该可以工作。
        猜你喜欢
        • 2021-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-13
        • 2019-08-25
        • 2021-09-17
        • 1970-01-01
        相关资源
        最近更新 更多