6 votes

Pandas IndexSlice échoue avec pd.style

Étant donné ce cadre de données :

In [1]: df = pd.DataFrame(np.random.rand(4,4),
                          index=['A','B','C','All'],
                          columns=[2011,2012,2013,'All']).round(2)
        print(df)
Out[1]:

     2011  2012  2013   All
A    0.94  0.17  0.06  0.64
B    0.49  0.16  0.43  0.64
C    0.16  0.20  0.22  0.37
All  0.94  0.04  0.72  0.18

J'essaie d'utiliser pd.style pour formater la sortie d'un dataframe. Un mot-clé est subset où vous définissez où appliquer vos règles de formatage (par exemple : mettre en évidence le maximum). La documentation de pd.style indique qu'il est préférable d'utiliser pd.IndexSlice pour ça :

La valeur passée à subset se comporte de la même manière que le découpage d'un DataFrame.

  • Un scalaire est traité comme une étiquette de colonne
  • Une liste (ou série ou tableau numpy)
  • Un tuple est traité comme (row_indexer, column_indexer)

Envisagez d'utiliser pd.IndexSlice pour construire le tuple du dernier.

J'essaie de comprendre pourquoi il échoue dans certains cas.

Disons que je veux appliquer une barre à toutes les lignes sauf la première et la dernière, et à toutes les colonnes sauf la dernière.

Ce site IndexSlice travaux :

In [2]: df.ix[pd.IndexSlice[1:-1,:-1]]
Out[2]:
   2011  2012  2013
B  0.49  0.16  0.43
C  0.16  0.20  0.22

Mais lorsqu'il est passé à style.bar ce n'est pas le cas :

In [3]: df.style.bar(subset=pd.IndexSlice[1:-1,:-1], color='#d65f5f')

TypeError: cannot do slice indexing on <class 'pandas.indexes.base.Index'>
with these indexers [1] of <class 'int'>

Alors que si je le passe légèrement différemment, ça marche :

In [4]: df.style.bar(subset=pd.IndexSlice[df.index[1:-1],df.columns[:-1]],
                     color='#d65f5f')

df.style.bar works as expected

Je ne comprends pas pourquoi ça ne fonctionne pas. Il semble qu'il y ait un manque de documentation en ce qui concerne pd.IndexSlice alors peut-être que je rate quelque chose. Il pourrait également s'agir d'un bogue dans pd.style (ce qui est assez nouveau, puisque 0.17.1 uniquement).

Quelqu'un peut-il expliquer ce qui ne va pas ?

6voto

AlexG Points 3695

C'est dommage que ce problème de compatibilité existe. D'après ce que je peux dire, vous répondez à votre propre question. Dans votre documentation, vous avez inclus la ligne :

Un tuple est traité comme (row_indexer, column_indexer)

Ce n'est pas ce que nous obtenons avec la première tranche :

In [1]: pd.IndexSlice[1:-1,:-1]
Out[2]: (slice(1, -1, None), slice(None, -1, None))

mais nous obtenons quelque chose de cette forme avec la méthode de la deuxième tranche :

In [3]: pd.IndexSlice[df.index[1:-1],df.columns[:-1]]
Out[4]: (Index(['B', 'C'], dtype='object'), Index([2011, 2012, 2013], dtype='object'))

Je ne pense pas que pd.IndexSlice ne fait rien d'autre que d'emballer le contenu dans un tuple pour ce deuxième cas. Vous pouvez simplement faire ça :

df.style.bar(subset=(df.index[1:-1],df.columns[:-1]),
                     color='#d65f5f')

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X