Спецификация фасета c легенда в каждом фасете Моря Моря FacetGrid - PullRequest
1 голос
/ 29 апреля 2020

Я пытаюсь создать легенду c с указанием фасета в каждом фасете объекта 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 становится довольно длинной. Вдохновленный ответом на другой пост , я выбираю итерацию по FacetGrid axes, используя g.axes.ravel(), чтобы получить легенду в каждом аспекте:

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, которые появляются в этом указанном c аспекте. Как мне добраться до этого?

towards a facet-specific legend

версии: pandas: 1.0.3; морское побережье: 0.10.0; python: 3.7.2

1 Ответ

2 голосов
/ 29 апреля 2020

Рассмотрим поэлементную итерацию с объектом groupby() с использованием zip для перестройки каждой легенды по соответствующим значениям столбца 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())

Plot Output

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...