web-dev-qa-db-fra.com

Seaplat boxplot + stripplot: légende en double

L'une des choses les plus intéressantes que vous pouvez facilement créer dans seaborn est la combinaison boxplot + stripplot:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

tips = sns.load_dataset("tips")

sns.stripplot(x="day", y="total_bill", hue="smoker",
data=tips, jitter=True,
palette="Set2", split=True,linewidth=1,edgecolor='gray')

sns.boxplot(x="day", y="total_bill", hue="smoker",
data=tips,palette="Set2",fliersize=0)

plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.);

boxplot+stripplot

Malheureusement, comme vous pouvez le voir ci-dessus, il a produit une double légende, une pour boxplot, une pour stripplot. De toute évidence, cela semble ridicule et redondant. Mais je n'arrive pas à trouver un moyen de me débarrasser de la légende stripplot et de ne laisser que la légende boxplot. Je peux probablement supprimer les éléments de plt.legend, mais je ne le trouve pas dans la documentation.

28
Sergey Antopolskiy

Vous pouvez obtenir quels descripteurs/étiquettes devraient exister dans la légende avant de dessiner la légende elle-même. Vous dessinez ensuite la légende uniquement avec celles que vous souhaitez.

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

tips = sns.load_dataset("tips")

sns.stripplot(x="day", y="total_bill", hue="smoker",
data=tips, jitter=True,
palette="Set2", split=True,linewidth=1,edgecolor='gray')

# Get the ax object to use later.
ax = sns.boxplot(x="day", y="total_bill", hue="smoker",
data=tips,palette="Set2",fliersize=0)

# Get the handles and labels. For this example it'll be 2 tuples
# of length 4 each.
handles, labels = ax.get_legend_handles_labels()

# When creating the legend, only use the first two elements
# to effectively remove the last two.
l = plt.legend(handles[0:2], labels[0:2], bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

example plot

26
Ffisegydd

Je veux ajouter que si vous utilisez des sous-tracés, la gestion des légendes pourrait être un peu plus problématique. Le code ci-dessus, qui donne d'ailleurs un chiffre très sympa (@Sergey Antopolskiy et @Ffisegydd), ne relocalisera pas la légende dans une sous-intrigue, qui continue d'apparaître très obstinément. Voir le code ci-dessus adapté aux sous-parcelles:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

tips = sns.load_dataset("tips")

fig, axes = sns.plt.subplots(2,2)

sns.stripplot(x="day", y="total_bill", hue="smoker",
              data=tips, jitter=True, palette="Set2", 
              split=True,linewidth=1,edgecolor='gray', ax = axes[0,0])

ax = sns.boxplot(x="day", y="total_bill", hue="smoker",
                 data=tips,palette="Set2",fliersize=0, ax = axes[0,0])

handles, labels = ax.get_legend_handles_labels()

l = plt.legend(handles[0:2], labels[0:2], bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

duplicated legend

La légende originale demeure. Pour l'effacer, vous pouvez ajouter cette ligne:

axes[0,0].legend(handles[:0], labels[:0])

corrected legend

Edit: dans les versions récentes de seaborn (> 0.9.0), cela laissait une petite boîte blanche dans le coin comme indiqué dans les commentaires. Pour le résoudre, utilisez la réponse dans cet article :

axes[0,0].get_legend().remove()
5
BossaNova