如何将图例放在seaborn.FacetGrid的第一个子图上?

时间:2015-11-10 13:30:09

标签: python matplotlib plot seaborn

我有一个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()

这会产生这个情节:

barplot-all

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

barplot1

和代码:

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)对我不起作用,因此我在此answer中使用plt.legend(legend_patches)作为评论。结果是:

bar test with legend in 3rd

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

测试2

最后,我尝试创建一个列包裹为2(col_wrap=2)的子图,其中包含了右下方的图例:

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

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

barplot 2cols

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

2 个答案:

答案 0 :(得分:5)

您可以使用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()

enter image description here

答案 1 :(得分: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)
    
  3. enter image description here