web-dev-qa-db-fra.com

Erreur "Impossible d'interpréter l'entrée" avec Seaborn lors du traçage des groupes

Dis que j'ai cette trame de données

d = {     'Path'   : ['abc', 'abc', 'ghi','ghi', 'jkl','jkl'],
          'Detail' : ['foo', 'bar', 'bar','foo','foo','foo'],
          'Program': ['prog1','prog1','prog1','prog2','prog3','prog3'],
          'Value'  : [30, 20, 10, 40, 40, 50],
          'Field'  : [50, 70, 10, 20, 30, 30] }


df = DataFrame(d)
df.set_index(['Path', 'Detail'], inplace=True)
df

               Field Program  Value
Path Detail                      
abc  foo        50   prog1     30
     bar        70   prog1     20
ghi  bar        10   prog1     10
     foo        20   prog2     40
jkl  foo        30   prog3     40
     foo        30   prog3     50

Je peux l'agréger sans problème (s'il y a une meilleure façon de le faire, au fait, j'aimerais savoir!)

df_count = df.groupby('Program').count().sort(['Value'], ascending=False)[['Value']]
df_count

Program   Value
prog1    3
prog3    2
prog2    1

df_mean = df.groupby('Program').mean().sort(['Value'], ascending=False)[['Value']]
df_mean

Program  Value
prog3    45
prog2    40
prog1    20

Je peux le tracer à partir de Pandas pas de problème ...

df_mean.plot(kind='bar')

Mais pourquoi est-ce que j'obtiens cette erreur quand je l'essaye dans seaborn?

sns.factorplot('Program',data=df_mean)
    ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-26-23c2921627ec> in <module>()
----> 1 sns.factorplot('Program',data=df_mean)

C:\Anaconda3\lib\site-packages\seaborn\categorical.py in factorplot(x, y, hue, data, row, col, col_wrap, estimator, ci, n_boot, units, order, hue_order, row_order, col_order, kind, size, aspect, orient, color, palette, legend, legend_out, sharex, sharey, margin_titles, facet_kws, **kwargs)
   2673     # facets to ensure representation of all data in the final plot
   2674     p = _CategoricalPlotter()
-> 2675     p.establish_variables(x_, y_, hue, data, orient, order, hue_order)
   2676     order = p.group_names
   2677     hue_order = p.hue_names

C:\Anaconda3\lib\site-packages\seaborn\categorical.py in establish_variables(self, x, y, hue, data, orient, order, hue_order, units)
    143                 if isinstance(input, string_types):
    144                     err = "Could not interperet input '{}'".format(input)
--> 145                     raise ValueError(err)
    146 
    147             # Figure out the plotting orientation

ValueError: Could not interperet input 'Program'
10
marshallbanana

La raison de l'exception que vous obtenez est que Program devient un index des trames de données df_mean et df_count après votre group_by opération.

Si vous vouliez obtenir le factorplot de df_mean, une solution simple consiste à ajouter l'index sous forme de colonne,

In [7]:

df_mean['Program'] = df_mean.index

In [8]:

%matplotlib inline
import seaborn as sns
sns.factorplot(x='Program', y='Value', data=df_mean)

Mais vous pouvez encore plus simplement laisser factorplot faire les calculs pour vous,

sns.factorplot(x='Program', y='Value', data=df)

Vous obtiendrez le même résultat. J'espère que ça aide.

MODIFIER après les commentaires

En effet, vous faites un très bon point sur le paramètre as_index; par défaut, il est défini sur True, et dans ce cas, Program devient une partie de l'index, comme dans votre question.

In [14]:

df_mean = df.groupby('Program', as_index=True).mean().sort(['Value'], ascending=False)[['Value']]
df_mean

Out[14]:
        Value
Program 
prog3   45
prog2   40
prog1   20

Juste pour être clair, de cette façon Program n'est plus une colonne, mais elle devient l'index. l'astuce df_mean['Program'] = df_mean.index conserve réellement l'index tel qu'il est et ajoute une nouvelle colonne pour l'index, afin que Program soit dupliqué maintenant.

In [15]:

df_mean['Program'] = df_mean.index
df_mean

Out[15]:
        Value   Program
Program     
prog3   45  prog3
prog2   40  prog2
prog1   20  prog1

Cependant, si vous définissez as_index à False, vous obtenez Program sous forme de colonne, plus un nouvel index d'auto-incrémentation,

In [16]:

df_mean = df.groupby('Program', as_index=False).mean().sort(['Value'], ascending=False)[['Program', 'Value']]
df_mean

Out[16]:
    Program Value
2   prog3   45
1   prog2   40
0   prog1   20

De cette façon, vous pouvez le nourrir directement dans seaborn. Néanmoins, vous pouvez utiliser df et obtenir le même résultat.

J'espère que ça aide.

15
lrnzcig