【问题标题】:How to put the legend on first subplot of seaborn.FacetGrid?如何将图例放在 seaborn.FacetGrid 的第一个子图上?
【发布时间】:2016-02-11 09:35:39
【问题描述】:

我有一个 pandas DataFrame df,我用 seaborn.barplot 的子图对其进行了可视化。 我的问题是我想将我的图例移到其中一个子图中。

要根据条件(在我的情况下为 Area)创建子图,我使用seaborn.FacetGrid。这是我使用的代码:

import matplotlib.pyplot as plt
import matplotlib
import seaborn as sns
# .. load data
grid = sns.FacetGrid(df, col="Area", col_order=['F1','F2','F3'])
bp = grid.map(sns.barplot,'Param','Time','Method')
bp.add_legend()
bp.set_titles("{col_name}")
bp.set_ylabels("Time (s)")
bp.set_xlabels("Number")
sns.plt.show()

这会产生这个情节:

你看到这里的图例完全在右边,但我想把它放在其中一个图中(例如左边的图),因为我的原始数据标签很长,而且图例占用了太多空间。这是仅 1 个图例位于图中的示例:

和代码:

mask = df['Area']=='F3'
ax=sns.barplot(x='Param',y='Time',hue='Method',data=df[mask])
sns.plt.show()

测试 1: 我尝试了answer 的示例,他们在其中一个子图中有图例:

grid = sns.FacetGrid(df, col="Area", col_order=['F1','F2','F3'])
bp = grid.map(sns.barplot,'Param','Time','Method')
Ax = bp.axes[0]
Boxes = [item for item in Ax.get_children()
     if isinstance(item, matplotlib.patches.Rectangle)][:-1]
legend_labels  = ['So1', 'So2', 'So3', 'So4', 'So5']
# Create the legend patches
legend_patches = [matplotlib.patches.Patch(color=C, label=L) for
              C, L in zip([item.get_facecolor() for item in Boxes],
                          legend_labels)]

# Plot the legend
plt.legend(legend_patches)    
sns.plt.show()

请注意,我更改了plt.legend(handles=legend_patches) 对我不起作用,因此我使用plt.legend(legend_patches),正如answer 中所评论的那样。然而结果是:

如您所见,图例位于第三个子图中,颜色和标签都不匹配。


测试 2

最后,我尝试创建一个列换行为 2 (col_wrap=2) 的子图,想法是在右下角放置图例:

grid = sns.FacetGrid(df, col="MapPubName", col_order=['F1','F2','F3'],col_wrap=2)

但这也会导致图例位于右侧:


问题:如何在第一个子图中获取图例?或者如何将图例移动到网格中的任何位置?

【问题讨论】:

    标签: python matplotlib plot seaborn


    【解决方案1】:

    您可以使用 grid.axes[i][j].legend() 在所需的特定轴上设置图例

    对于1 row, 3 column 网格的情况,您希望将grid.axes[0][0].legend() 设置为在左侧绘图。

    这是一个从您的代码派生的简单示例,但已针对示例数据集进行了更改。

    import matplotlib.pyplot as plt
    import matplotlib
    import seaborn as sns
    
    df = sns.load_dataset("tips")
    
    grid = sns.FacetGrid(df, col="day")
    bp = grid.map(sns.barplot,"time",'total_bill','sex')
    
    grid.axes[0][0].legend()
    
    bp.set_titles("{col_name}")
    bp.set_ylabels("Time (s)")
    bp.set_xlabels("Number")
    sns.plt.show()
    

    【讨论】:

    • @Rockbar 它适用于 seaborn 0.8.1;你用的是什么版本?
    • 我有相同的版本。注意:“AxesSubplot”对象不支持索引
    • 看起来你只有一个子情节?您是复制上面的示例还是在您自己的代码中?如果您只有一个子图,则不需要 [0][0]
    • 实际上,我正在使用与 Facetgrid 和 map 非常相似的代码,但不是 sns.barplot,而是包含 plt.scatter 的扩展函数。我会尝试 sns.regplot,或者。
    【解决方案2】:
    1. 使用legend_out=False 选项。

    2. 如果您正在制作多面条形图,您应该使用factorplotkind=bar。否则,如果您没有明确指定每个方面的顺序,您的绘图可能最终会出错。

      import seaborn as sns
      tips = sns.load_dataset("tips")
      sns.factorplot(x="sex", y="total_bill", hue="smoker", col="day",
                     data=tips, kind="bar", aspect=.7, legend_out=False)
      

    【讨论】:

    • 嗨!很棒的包裹!您将如何使用此选项将图例移动到另一个方面?
    • 另外,是否可以将图例移动到 FacetGrid 的空白处?假设你有 3 个地块,在 2x2 网格中,就像在黄金问题中一样
    猜你喜欢
    • 2021-01-04
    • 2016-03-24
    • 1970-01-01
    • 2017-05-24
    • 2012-04-27
    • 2012-10-14
    • 2012-06-10
    • 1970-01-01
    • 2018-07-18
    相关资源
    最近更新 更多