web-dev-qa-db-fra.com

Pandas Python: L'ordre est-il préservé lors de l'utilisation de groupby () et agg ()?

J'ai souvent utilisé la fonction agg() de pandas pour générer des statistiques récapitulatives sur chaque colonne d'un data.frame. Par exemple, voici comment vous produiriez l'écart moyen et l'écart type:

df = pd.DataFrame({'A': ['group1', 'group1', 'group2', 'group2', 'group3', 'group3'],
                   'B': [10, 12, 10, 25, 10, 12],
                   'C': [100, 102, 100, 250, 100, 102]})

>>> df
[output]
        A   B    C
0  group1  10  100
1  group1  12  102
2  group2  10  100
3  group2  25  250
4  group3  10  100
5  group3  12  102

Dans ces deux cas, l'ordre dans lequel les lignes individuelles sont envoyées à la fonction agg n'a pas d'importance. Mais considérons l'exemple suivant, qui:

df.groupby('A').agg([np.mean, lambda x: x.iloc[1] ])

[output]

        mean  <lambda>  mean  <lambda>
A                                     
group1  11.0        12   101       102
group2  17.5        25   175       250
group3  11.0        12   101       102

Dans ce cas, le lambda fonctionne comme prévu et affiche la deuxième ligne de chaque groupe. Cependant, je n'ai rien trouvé dans la documentation des pandas qui implique que cela est garanti dans tous les cas. Je veux utiliser agg() avec une fonction de moyenne pondérée, donc je veux être sûr que les lignes qui entrent dans la fonction seront dans le même ordre qu'elles apparaissent dans le bloc de données d'origine.

Est-ce que quelqu'un sait, idéalement via quelque part dans le code source de docs ou de pandas, si cela est garanti?

23
BringMyCakeBack

Voir cette amélioration issue

La réponse courte est oui, le groupe conservera les ordres tels qu'ils ont été passés. Vous pouvez le prouver en utilisant votre exemple comme ceci:

In [20]: df.sort_index(ascending=False).groupby('A').agg([np.mean, lambda x: x.iloc[1] ])
Out[20]: 
           B             C         
        mean <lambda> mean <lambda>
A                                  
group1  11.0       10  101      100
group2  17.5       10  175      100
group3  11.0       10  101      100

Ce n'est pas vrai pour resample cependant car il nécessite un index monotone (cela fonctionnera avec un index non monotone, mais le triera en premier).

Leur est un drapeau sort= à groupby, mais cela concerne le tri des groupes eux-mêmes et non les observations au sein d'un groupe.

FYI: df.groupby('A').nth(1) est un moyen sûr d’obtenir la 2e valeur d’un groupe (car votre méthode ci-dessus échouera si un groupe a <2 éléments)

17
Jeff

La doc 0.19.1 de Panda dit "groupby préserve l'ordre des lignes dans chaque groupe", ce qui garantit son comportement.

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html

7
Uwe Mayer

Afin de préserver l'ordre, vous devrez passer .groupby(..., sort=False). Dans votre cas, la colonne de regroupement est déjà triée, cela ne fait donc aucune différence, mais vous devez généralement utiliser l'indicateur sort=False:

 df.groupby('A', sort=False).agg([np.mean, lambda x: x.iloc[1] ])
0
Dima Lituiev

Encore plus facile:

  import pandas as pd
  pd.pivot_table(df,index='A',aggfunc=(np.mean))

sortie:

            B    C
     A                
   group1  11.0  101
   group2  17.5  175
   group3  11.0  101
0
TinaW