Seaborn pairplot传奇 - 如何控制位置

时间:2016-06-14 15:06:34

标签: python python-2.7 matplotlib seaborn

我想在散点图矩阵之外移动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')

上述代码的输出是此文件:output file

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

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

3 个答案:

答案 0 :(得分:10)

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)

pairplot

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

PairGrid具有引用fig实例的Figure属性的事实未记录在案。无论如何,这是一个简单的猜测,我可以使用fig = plt.gcf()代替。

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

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

您也可以创建自己的句柄,但这很麻烦,这就是为什么我寻找快捷方式,即使没有文档。

答案 1 :(得分:3)

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

Example with button to click circled

答案 2 :(得分:1)

要控制默认线对图例的位置,

 class TagCollection
{
    [JsonProperty("tags")]
    public List<Tag> Tags { get; set; }
}

public class Tag
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("value")]
    public string Value { get; set; }
}

private TagCollection tagCollection;  

private void createCollection(){

    tagCollection.Tags.Add(
        new Tag { Name = "Test", Id = "tag1", Value = "145" }
    );

}