Regrouper les boxplots en seaborn quand input est une DataFrame

j'ai l'intention de tracer plusieurs colonnes dans un pandas dataframe, tous regroupés par une autre colonne en utilisant groupby à l'intérieur seaborn.boxplot. Il y a une bonne réponse ici, pour un problème similaire dans matplotlibmatplotlib: Groupe boxplots mais étant donné le fait que seaborn.boxplot vient groupby option j'ai pensé qu'il pourrait être beaucoup plus facile de le faire dans seaborn.

voici un exemple reproductible qui échoue:

import seaborn as sns
import pandas as pd
df = pd.DataFrame(
[
[2, 4, 5, 6, 1],
[4, 5, 6, 7, 2],
[5, 4, 5, 5, 1],
[10, 4, 7, 8, 2],
[9, 3, 4, 6, 2],
[3, 3, 4, 4, 1]
], columns=['a1', 'a2', 'a3', 'a4', 'b'])

#Plotting by seaborn
sns.boxplot(df[['a1','a2', 'a3', 'a4']], groupby=df.b)

ce que j'obtiens est quelque chose qui ignore complètement groupby option:

Failed groupby

alors que si je fais ceci avec une colonne cela fonctionne grâce à une autre question SO Seaborn groupby pandas Series:

sns.boxplot(df.a1, groupby=df.b)

seaborn that does not fail

Donc je voudrais obtenir tous mes colonnes dans une parcelle (toutes les colonnes viennent dans une échelle similaire).

EDIT:

ci-dessus DONC, la question a été modifié et comprend maintenant un "pas propre" réponse à ce problème, mais il ce serait bien si quelqu'un a une meilleure idée pour ce problème.

17
demandé sur Community 2014-08-13 15:24:00

3 réponses

comme le font remarquer les autres réponses, le boxplot fonction est limitée à tracer une seule "couche" de boxplots, et le groupby paramètre n'a d'effet que lorsque l'entrée est une Série et que vous avez une deuxième variable que vous souhaitez utiliser pour bin les observations dans chaque boîte..

Toutefois, vous pouvez accomplir ce que je pense que vous êtes l'espoir pour le factorplot fonction à l'aide de kind="box". Mais, vous devrez d'abord "fondre" le dataframe de l'échantillon dans ce qu'on appelle la forme longue ou le format "ordonné" où chaque colonne représente une variable et chaque ligne est une observation:

df_long = pd.melt(df, "b", var_name="a", value_name="c")

il est Alors très simple de parcelle:

sns.factorplot("a", hue="b", y="c", data=df_long, kind="box")

enter image description here

22
répondu mwaskom 2014-08-13 14:47:35

la fonction groupby de Seaborn prend les séries et non les images, c'est pourquoi elle ne fonctionne pas.

comme un travail autour, vous pouvez faire ceci:

fig, ax = plt.subplots(1,2, sharey=True)
for i, grp in enumerate(df.filter(regex="a").groupby(by=df.b)):
    sns.boxplot(grp[1], ax=ax[i])

ça donne : sns

Notez que df.filter(regex="a") est équivalent à df[['a1','a2', 'a3', 'a4']]

   a1  a2  a3  a4
0   2   4   5   6
1   4   5   6   7
2   5   4   5   5
3  10   4   7   8
4   9   3   4   6
5   3   3   4   4

Espérons que cette aide

4
répondu jrjc 2014-08-13 14:35:35

Ce n'est pas vraiment mieux que la réponse est lié, mais je pense que la manière d'y parvenir dans seaborn est l'aide de l' FacetGrid car le paramètre groupby n'est défini que pour les séries passées à la fonction boxplot.

voici un peu de code-le pd.melt est nécessaire parce que (comme je peux le dire) la cartographie de la facette ne peut prendre que des colonnes individuelles comme paramètres, de sorte que les données doivent être transformées en un "long" format.

g = sns.FacetGrid(pd.melt(df, id_vars='b'), col='b')
g.map(sns.boxplot, 'value', 'variable')

faceted seaborn boxplot

3
répondu chrisb 2014-08-13 11:55:26