如何将图例放在 seaborn.FacetGrid 的第一个子图中?
How to put the legend on first subplot of seaborn.FacetGrid?
我有一个 pandas DataFrame df
,我用 seaborn.barplot
的子图可视化它。 我的问题是我想将图例移动到其中一个子图中。
要根据条件创建子图(在我的例子中是面积),我使用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()
生成此图:
你看这里的图例完全在右边,但我想把它放在其中一个图中(例如左边的图),因为我的原始数据标签很长而且图例占了太多space。这是只有 1 个图的示例,其中图例位于图内:
和代码:
mask = df['Area']=='F3'
ax=sns.barplot(x='Param',y='Time',hue='Method',data=df[mask])
sns.plt.show()
测试 1:
我尝试了一个 的例子,其中一个子图有图例:
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)
但这也导致图例位于右侧:
问题:如何获取第一个子图中的图例?或者如何将图例移动到网格中的任意位置?
您可以使用 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()
使用 legend_out=False
选项。
如果您正在制作多面条形图,您应该使用 factorplot
和 kind=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)
我有一个 pandas DataFrame df
,我用 seaborn.barplot
的子图可视化它。 我的问题是我想将图例移动到其中一个子图中。
要根据条件创建子图(在我的例子中是面积),我使用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()
生成此图:
你看这里的图例完全在右边,但我想把它放在其中一个图中(例如左边的图),因为我的原始数据标签很长而且图例占了太多space。这是只有 1 个图的示例,其中图例位于图内:
和代码:
mask = df['Area']=='F3'
ax=sns.barplot(x='Param',y='Time',hue='Method',data=df[mask])
sns.plt.show()
测试 1:
我尝试了一个
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)
但这也导致图例位于右侧:
问题:如何获取第一个子图中的图例?或者如何将图例移动到网格中的任意位置?
您可以使用 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()
使用
legend_out=False
选项。如果您正在制作多面条形图,您应该使用
factorplot
和kind=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)