【问题标题】:A facet-specific legend in each facet of a FacetGrid SeabornFacetGrid Seaborn 的每个方面中的特定于方面的图例
【发布时间】:2020-04-29 13:59:53
【问题描述】:

我正在尝试在FacetGrid Seaborn 对象的每个方面制作一个特定于方面的图例,例如由catplot 生成的图例。 考虑以下DataFrame,其中measurement 是要针对分类Condition 绘制的变量,根据变量Lab 和(仪器)model 跨行和列分面。 hue 设置为进行测量的特定仪器的序列号。 这是DataFrame

df = pd.DataFrame({'Condition': ['C1','C2','C1','C2','C1','C1','C2','C1',
                                 'C1','C1', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C2'],
                   'model': ['Pluto','Pluto','Jupy','Jupy','Jupy','Jupy','Jupy','Jupy',
                             'Jupy', 'Pluto', 'Pluto', 'Pluto', 'Pluto', 'Pluto', 'Jupy', 'Jupy',
                             'Pluto'],
                   'serial': [2520,2520,3568,3568,3568,3580,3580,356,
                              456, 2580, 2580, 2580, 2599, 2599, 2700, 2700, 
                              2560],
                   'measurement': [1.02766,1.0287,1.0099,1.0198,1.0034,1.0036,1.0054,1.0024,
                            1.0035,1.00245,1.00456, 1.01, 1.0023, 1.0024, 1.00238, 1.0115, 
                            1.020],
                   'Lab': ['John','John','John','John','Jack','Jack','Jack','John',
                           'Jack','John', 'Jack', 'Jack', 'Jack', 'Jack', 'John', 'John', 
                           'John']}
                  )

某些方面仅包含hue 级别的子集,并且随着级别数量的增加,FacetGrid 图例变得相当长。受到另一个post 的答案的启发,我选择使用g.axes.ravel() 遍历FacetGrid axes 以获得每个方面的图例:

sns.set_style("ticks")
g = sns.catplot(x='Condition', # returns a FacetGrid object for further editing
            y = 'measurement', 
            data=df, 
            hue='serial',
            row='Lab', 
            col='model',
            s=10,
            kind='swarm',
            dodge=False, 
            aspect = 1,
            sharey = True,
            legend_out = True,
            ).despine(left=True)

for axes in g.axes.ravel():
    axes.legend()
g.savefig('/Users/massimopinto/Desktop/legend_in_facets.png', 
          bbox_inches='tight')

这会导致整个FacetGrid 对象图例中的情节相当拥挤和信息过多。我希望拥有的是每个方面的图例以显示出现在该特定方面的hue 级别。 我该怎么做?

版本:熊猫:1.0.3;海生:0.10.0;蟒蛇:3.7.2

【问题讨论】:

    标签: python pandas seaborn


    【解决方案1】:

    考虑使用zipgroupby() 对象进行逐元素迭代,以通过hue 列的相应值重建每个图例。重要的是,您必须在绘图前对数据框进行排序。

    df = df.sort_values(['Lab', 'model', 'serial']).reset_index(drop=True)
    
    sns.set_style("ticks")
    g = sns.catplot(x = 'Condition',                  
                    y = 'measurement', 
                    data = df, 
                    hue = 'serial',
                    row = 'Lab', 
                    col = 'model',
                    s=10,
                    kind='swarm',
                    dodge=False, 
                    aspect = 1,
                    sharey = True,
                    legend_out = False,               # REMOVE MASTER LEGEND
                   ).despine(left=True)
    
    # MASTER SERIES OF serial
    ser_vals = pd.Series(df['serial'].sort_values().unique())
    
    for axes, (i, d) in zip(g.axes.ravel(), df.groupby(['Lab', 'model'])):
        handles, labels = axes.get_legend_handles_labels()
    
        # SUBSET MASTER SERIES OF serial
        vals = ser_vals[ser_vals.isin(d['serial'].unique())]    
        idx = vals.index.tolist()
    
        if len(idx) > 0:
           axes.legend(handles = [handles[i] for i in idx], 
                       labels = vals.tolist())
    

    【讨论】:

    • 谢谢。我最好把它放到一个函数中以供重用。希望这有望成为seaborn 中的未来传奇功能。
    • 是的,听起来很有用。由于seaborn 是开源的,可能会为项目做出贡献或suggest it as a request
    • 当我了解更多如何使用它时,为该项目做出贡献会很棒。同时,我听从了你的建议,发了fresh request
    • 你的回答,@Parfait,将其整理出来,但一般程序应考虑axes 的数量和groupby 对象的大小不是 i> 一样。当一个或多个方面为空时(我在另一个数据框中有一个这样的情况),即在特定方面没有要绘制的数据时,一个以list index out of range 行中的list index out of range 错误结束,即 par你的回答。一种解决方案可能是删除关键的axes,它过于手动,无法成为通用方法。
    • 查看更新,使用if 逻辑有条件地向每个构面轴添加调整后的图例。
    猜你喜欢
    • 2018-12-28
    • 2015-09-19
    • 2019-07-30
    • 2020-07-29
    • 2022-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    相关资源
    最近更新 更多