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?
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)
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
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] ])
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