Seaborn pairplot 图例 - 如何控制位置

Posted

技术标签:

【中文标题】Seaborn pairplot 图例 - 如何控制位置【英文标题】:Seaborn pairplot legend - how to control position 【发布时间】:2016-10-15 09:47:35 【问题描述】:

我想将 Seaborn 配对图图例移到散点图矩阵之外。官方docs不给关键字legend。我正在尝试同时在 3 个不同的位置绘制图例之外的图例:底部中心、顶部中心、右侧中心

我试过这个:

import matplotlib.pyplot as plt
import seaborn as sns
iris = sns.load_dataset("iris")
g = sns.pairplot(iris,hue='species', palette='husl', markers='d', size=2.5, plot_kws=
    
    "s":40,
    "alpha":1.0,
    'lw':0.5,
    'edgecolor':'k'
    )
plt.legend(loc='upper center', bbox_to_anchor=(1.10, 1.0), ncol=1) #vertical legend
plt.legend(loc='lower center', bbox_to_anchor=(0.0, -0.15), ncol=3) #horizontal legend bottom
plt.legend(loc='upper left', bbox_to_anchor=(0.0, 1.15), ncol=3) #horizontal legend top
g.savefig('Test.png', bbox_inches='tight')

上面代码的输出是这个文件:。

所有 3 个图例都打印不正确。我不确定它是否在做我要求的定位。我不确定右边发生了什么 - 似乎出现了 2 个垂直图例,并且由于某种原因它们完全相互重叠。两个横向图例之一根本没有出现。

有没有办法避免垂直图例重叠,并将图例放在图外的 3 个位置 - 顶部中心、底部中心、右中心?

【问题讨论】:

默认位置是垂直方向在右侧外侧,如 here 所示。但是,必须有一种方法可以在这三个位置之一绘制图例。这里有什么建议吗? 【参考方案1】:

控制默认pairplot图例的位置:

    g._legend.set_bbox_to_anchor((0.5, 0.5))

【讨论】:

这是最有用的回应,IMO 作为补充,(0,0)是左下角,(1,1)是右上角,就像普通坐标系一样。所以默认应该是 (1, 0.5)。 要注意,至少在 Seaborn 0.11.1 g.legend 可用于访问图例对象,如果您不想感觉自己正在访问私有属性。【参考方案2】:

pairplot 已经在绘图矩阵之外添加了一个图例,并且不清楚您要将它移动到哪里。其他图例可能会按照您的要求进行定位,即使这可能不是您真正想要的。

plt.legend 会将图例附加到当前轴,每个轴只能有一个图例,因此在您的代码中只绘制最后一个图例。但是您可以将多个图例附加到一个图形上,而 IIUC 则希望相对于图形定位这些图例,因此图形图例似乎是最佳选择。

为了绘制图形图例,您需要显式传递处理程序和标签。为此,我必须使用私有属性 PairPlot._legend_data,但我没有找到使用公共 API 的方法。

不幸的是,matplotlib 不会自动腾出空间来容纳这些图例,除非您进行一些调整,否则它们将与子图重叠。我将只使用subplot_adjust 和一些在这种情况下对我有用的硬编码值,因为计算很棘手。

所以这是希望做你想要的代码:

g = sns.pairplot(iris, hue='species', palette='husl', markers='d', size=2.5, plot_kws=
    
    "s":40,
    "alpha":1.0,
    'lw':0.5,
    'edgecolor':'k'
    )

handles = g._legend_data.values()
labels = g._legend_data.keys()
g.fig.legend(handles=handles, labels=labels, loc='upper center', ncol=1)
g.fig.legend(handles=handles, labels=labels, loc='lower center', ncol=3)
g.fig.legend(handles=handles, labels=labels, loc='upper left', ncol=3)
g.fig.subplots_adjust(top=0.92, bottom=0.08)

OP 在评论中询问这是否可以在 seaborn 文档中找到。当然,其中一部分只是纯 matplotlib,并非特定于 seaborn。但我也意识到我必须依赖几个未记录的功能。

PairGrid 具有引用 Figure 实例的 fig 属性这一事实未记录在案。无论如何,这很容易猜到,我可以改用fig = plt.gcf()

获取图例的标签和句柄比较棘手。我通过查看PairGrid.add_legend的文档字符串了解了_legend_data属性,但是文档字符串本身有点隐藏(它不会出现在网络中)并且该属性带有下划线,好像它是私有的,所以使用它感觉不舒服。我发现在公共方法的文档字符串中提到私有属性是不一致的,可能我们应该将legend_data 作为公共属性,但我离题了。

或者,您可以尝试从子图中提取标签和句柄。您可能会猜到子图有这些信息,但没有实际的保证,所以这意味着依赖于无证行为。事实证明,非对角线的子图有它(但对角线的子图没有,所以如果你只看第一个子图,你会被误导),你可以做handles, labels = fig.get_axes()[1].get_legend_handles_labels()。但正如我所说,即使您只使用记录在案的 API,这也是未记录的行为。

您也可以创建自己的句柄,但这会很麻烦,这就是我寻找快捷方式的原因,即使没有记录。

【讨论】:

谢谢!这就是问题的答案。您是否在 seaborn 文档中找到了这个? @WR 我编辑了答案,如果我没有解决您的问题,请告诉我。 完成。好帖子!关于这个问题我没有进一步的问题。非常感谢,@Goyo! 如果这种方法的一个副作用是文本 species 从新的图例位置丢失。 @WR g.fig.legend(title='species', handles=handles, labels=labels, loc='upper center', ncol=1)【参考方案3】:

这实际上比您想象的要容易得多。它只是实际 matplot 输出中的默认设置。只需转到输出窗口顶部的配置子图按钮,然后稍微降低右边框上限,它就会被修复。

【讨论】:

哦,我明白了,所以你先创建一个 Python 图形,然后设置图例位置,然后将其保存到图像中。所以你是说没有办法以编程方式设置它? 是的,我找不到。问题是 matplot 无法将其识别为表格。我想你可以深入研究 pairplot 脚本并在那里修改它,但我认为它不能像你(和我)最初尝试的那样进行编辑。我在 GitHub 上看到了同样的问题,也没有人发现它。

以上是关于Seaborn pairplot 图例 - 如何控制位置的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Pairplot (seaborn) 中使用科学记数法

如何更改 seaborn pairplot 中仅 x 或 y 标签的字体大小?

sns.pairplot 中的图例未完全显示

在seaborn tsplot中将图例移到图外

机器学习——可视化绘图matplotlib和seaborn

斯科特是谁? - Seaborn pairplot 中的 ValueError:无法将字符串转换为浮点数:'scott'