web-dev-qa-db-fra.com

Avantages du multiindex de panda?

J'ai donc appris que je peux utiliser DataFrame.groupby sans avoir un MultiIndex pour faire des sous-échantillonnages/coupes transversales.

D'un autre côté, lorsque j'ai un MultiIndex sur un DataFrame, j'ai toujours besoin d'utiliser DataFrame.groupby pour faire du sous-échantillonnage/coupes transversales.

Alors, à quoi sert un MultiIndex en dehors de l'affichage assez utile et joli des hiérarchies lors de l'impression?

34
K.-Michael Aye

L'indexation hiérarchique (également appelée indexation "à plusieurs niveaux") a été introduite dans la version pandas 0.4).

Cela ouvre la porte à une analyse et une manipulation des données assez sophistiquées, en particulier pour travailler avec des données de dimension supérieure. En substance, il vous permet de stocker et de manipuler efficacement des données de dimension arbitrairement élevée dans une structure tabulaire à 2 dimensions (DataFrame), par exemple.

Imaginez construire une trame de données en utilisant MultiIndex comme ceci: -

import pandas as pd
import numpy as np

np.arrays = [['one','one','one','two','two','two'],[1,2,3,1,2,3]]

df = pd.DataFrame(np.random.randn(6,2),index=pd.MultiIndex.from_tuples(list(Zip(*np.arrays))),columns=['A','B'])

df  # This is the dataframe we have generated

          A         B
one 1 -0.732470 -0.313871
    2 -0.031109 -2.068794
    3  1.520652  0.471764
two 1 -0.101713 -1.204458
    2  0.958008 -0.455419
    3 -0.191702 -0.915983

Ce df est simplement une structure de données à deux dimensions

df.ndim

2

Mais nous pouvons l'imaginer, en regardant la sortie, comme une structure de données en 3 dimensions.

  • one avec 1 avec données -0.732470 -0.313871.
  • one avec 2 avec données -0.031109 -2.068794.
  • one avec 3 avec données 1.520652 0.471764.

A.k.a .: "stocker et manipuler efficacement des données de dimensions arbitrairement élevées dans une structure tabulaire bidimensionnelle"

Ce n'est pas seulement un "joli affichage". Il présente l'avantage de retrouver facilement les données, car nous avons maintenant un index hiérarchique.

Par exemple.

In [44]: df.ix["one"]
Out[44]: 
          A         B
1 -0.732470 -0.313871
2 -0.031109 -2.068794
3  1.520652  0.471764

nous donnera une nouvelle trame de données uniquement pour le groupe de données appartenant à "un".

Et nous pouvons affiner notre sélection de données en procédant ainsi: -

In [45]: df.ix["one"].ix[1]
Out[45]: 
A   -0.732470
B   -0.313871
Name: 1

Et bien sûr, si nous voulons une valeur spécifique, voici un exemple: -

In [46]: df.ix["one"].ix[1]["A"]
Out[46]: -0.73247029752040727

Donc, si nous avons encore plus d'index (en plus des 2 index illustrés dans l'exemple ci-dessus), nous pouvons essentiellement explorer et sélectionner l'ensemble de données qui nous intéresse vraiment sans avoir besoin de groupby.

Nous pouvons même saisir une coupe transversale (lignes ou colonnes) de notre dataframe ...

Par rangées: -

In [47]: df.xs('one')
Out[47]: 
          A         B
1 -0.732470 -0.313871
2 -0.031109 -2.068794
3  1.520652  0.471764

Par colonnes: -

In [48]: df.xs('B', axis=1)
Out[48]: 
one  1   -0.313871
     2   -2.068794
     3    0.471764
two  1   -1.204458
     2   -0.455419
     3   -0.915983
Name: B
61
Calvin Cheng

Excellent article de @Calvin Cheng, mais j'ai pensé que j'essaierais aussi.

Quand utiliser un MultiIndex:

  1. Lorsque la valeur d'une seule colonne n'est pas suffisante pour identifier de manière unique une ligne.
  2. Lorsque les données sont logiquement hiérarchiques - ce qui signifie qu'elles ont plusieurs dimensions ou "niveaux".

Pourquoi (votre question principale) - au moins ce sont les plus grands avantages de l'OMI:

  1. Manipulation facile via stack () et unstack ()
  2. Mathématiques faciles lorsqu'il y a plusieurs niveaux de colonne
  3. Sucre syntaxique pour trancher/filtrer

Exemple:

                                                       Dollars  Units
Date       Store   Category Subcategory UPC EAN
2018-07-10 Store 1 Alcohol  Liqour      80480280024    154.77      7
           Store 2 Alcohol  Liqour      80480280024     82.08      4
           Store 3 Alcohol  Liqour      80480280024    259.38      9
           Store 1 Alcohol  Liquor      80432400630    477.68     14
                                        674545000001   139.68      4
           Store 2 Alcohol  Liquor      80432400630    203.88      6
                                        674545000001   377.13     13
           Store 3 Alcohol  Liquor      80432400630    239.19      7
                                        674545000001   432.32     14
           Store 1 Beer     Ales        94922755711     65.17      7
                                        702770082018   174.44     14
                                        736920111112    50.70      5
           Store 2 Beer     Ales        94922755711    129.60     12
                                        702770082018   107.40     10
                                        736920111112    59.65      5
           Store 3 Beer     Ales        94922755711    154.00     14
                                        702770082018   137.40     10
                                        736920111112   107.88     12
           Store 1 Beer     Lagers      702770081011   156.24     12
           Store 2 Beer     Lagers      702770081011   137.06     11
           Store 3 Beer     Lagers      702770081011   119.52      8    

1) Si nous voulons comparer facilement les ventes entre les magasins, nous pouvons utiliser df.unstack('Store') pour tout aligner côte à côte:

                                             Dollars                   Units
Store                                        Store 1 Store 2 Store 3 Store 1 Store 2 Store 3
Date       Category Subcategory UPC EAN
2018-07-10 Alcohol  Liqour      80480280024   154.77   82.08  259.38       7       4       9
                    Liquor      80432400630   477.68  203.88  239.19      14       6       7
                                674545000001  139.68  377.13  432.32       4      13      14
           Beer     Ales        94922755711    65.17  129.60  154.00       7      12      14
                                702770082018  174.44  107.40  137.40      14      10      10
                                736920111112   50.70   59.65  107.88       5       5      12
                    Lagers      702770081011  156.24  137.06  119.52      12      11       8

2) Nous pouvons également facilement faire des calculs sur plusieurs colonnes. Par exemple, df['Dollars'] / df['Units'] Divisera ensuite les dollars de chaque magasin par ses unités, pour chaque magasin sans opérations multiples:

Store                                         Store 1  Store 2  Store 3
Date       Category Subcategory UPC EAN
2018-07-10 Alcohol  Liqour      80480280024     22.11    20.52    28.82
                    Liquor      80432400630     34.12    33.98    34.17
                                674545000001    34.92    29.01    30.88
           Beer     Ales        94922755711      9.31    10.80    11.00
                                702770082018    12.46    10.74    13.74
                                736920111112    10.14    11.93     8.99
                    Lagers      702770081011    13.02    12.46    14.94

3) Si nous voulons ensuite filtrer sur des lignes spécifiques, au lieu d'utiliser le

df[(df[col1] == val1) and (df[col2] == val2) and (df[col3] == val3)]

format, nous pouvons à la place .xs ou .query (oui ceux-ci fonctionnent pour les dfs ordinaires, mais ce n'est pas très utile). La syntaxe serait plutôt:

df.xs((val1, val2, val3), level=(col1, col2, col3))

Plus d'exemples peuvent être trouvés dans ce cahier de tutoriel J'ai mis en place.

9
ZaxR