Pandas GroupBy : Aggregation, Transform, Apply (Guide 2025)
Updated on
Le modèle split-apply-combine est le point fort de Pandas. Problème : difficile de choisir entre agg, transform ou apply, et on se heurte vite au tri implicite, aux groupes manquants ou aux effets de SettingWithCopy.
Cadre PAS :
- Problème : Les calculs groupés semblent opaques et lents quand on ne veut que des totaux ou des ratios par ligne.
- Agiter : Un
applyexcessif ou l’oubli deas_index=Falseproduit des formes inattendues, des colonnes dupliquées et du code lent. - Solution : Quelques recettes suffisent—
aggpour les résumés,transformpour les features par ligne,applyseulement si nécessaire—avec des options de tri et de gestion des groupes manquants.
Référence rapide : quand utiliser chaque méthode
| Méthode | Forme renvoyée | Idéal pour | Exemple |
|---|---|---|---|
agg / aggregate | Une ligne par groupe | Résumés et multi-métriques | df.groupby("team").agg(avg_score=("score","mean")) |
transform | Même longueur | Features par ligne dépendant du groupe | df["z"] = df.groupby("team")["score"].transform("zscore") |
apply | Flexible | Reshapes complexes quand agg/transform ne suffisent pas | df.groupby("team").apply(custom_fn) |
Données d’exemple
import pandas as pd
data = {
"team": ["A", "A", "B", "B", "B", "C"],
"player": ["x1", "x2", "y1", "y2", "y3", "z1"],
"score": [9, 7, 8, 6, 10, 3],
"minutes": [30, 25, 28, 32, 20, 15],
}
df = pd.DataFrame(data)Modèles d’agrégation (agg)
summary = (
df.groupby("team", as_index=False)
.agg(
avg_score=("score", "mean"),
max_score=("score", "max"),
minutes_played=("minutes", "sum"),
)
)- Utilisez la named aggregation pour garder des noms propres.
as_index=Falseconserveteamen colonne (utile pour merges/plots).sort=Falsegarde l’ordre d’entrée si nécessaire.
Multi-agrégation sur une colonne
df.groupby("team", as_index=False).agg(
score_mean=("score", "mean"),
score_std=("score", "std"),
score_count=("score", "size"),
)Features diffusées (transform)
transform garde la forme originale et ajoute les métriques de groupe à chaque ligne.
df["score_pct_of_team"] = (
df["score"] / df.groupby("team")["score"].transform("sum")
)Z-score par équipe :
df["score_z"] = (
df.groupby("team")["score"]
.transform(lambda s: (s - s.mean()) / s.std(ddof=0))
)Utilisez transform pour :
- Ratios par rapport aux totaux de groupe
- Scores normalisés
- Flags de groupe (ex.
rank,cumcount)
Quand apply vaut le coup
apply est flexible mais plus lent ; réservez-le quand agg/transform ne suffisent pas.
def top_n(group, n=2):
return group.nlargest(n, "score")
top_players = df.groupby("team").apply(top_n, n=1).reset_index(drop=True)Préférez agg/transform; utilisez apply si :
- vous devez renvoyer un nombre variable de lignes par groupe ;
- la logique nécessite du Python non vectorisé.
Groupes manquants et tri
result = (
df.groupby("team", dropna=False, sort=False)
.agg(avg_score=("score", "mean"))
)dropna=Falseconserve les étiquettesNaN.sort=Falseévite le réordonnancement—utile si l’ordre a du sens.
GroupBy avec plusieurs clés et index
multi = (
df.groupby(["team", "player"], as_index=False)
.agg(score_mean=("score", "mean"))
)Groupement par niveaux d’index :
df2 = df.set_index(["team", "player"])
df2.groupby(level="team")["score"].mean()Pièges fréquents
| Problème | Correction |
|---|---|
Formes inattendues (Series vs DataFrame) | Mettez as_index=False ou ensuite reset_index(). |
| Noms de colonnes dupliqués après merge | Utilisez la named aggregation pour définir les noms. |
Lenteur due à apply | Remplacez par agg/transform ou des méthodes vectorisées. |
| Catégories manquantes en sortie | Laissez observed=False (défaut) ou assurez les catégories ; dropna=False pour NaN. |
Conseils export et visualisation
- Après agrégation, triez pour présenter :
summary.sort_values("avg_score", ascending=False). - Pour des graphiques, pivotez le résumé :
summary.pivot(index="team", values="avg_score").
Guides liés
À retenir
aggpour les résumés,transformpour les features par ligne,applyavec parcimonie.- Contrôlez la forme avec
as_indexetreset_index. - Gérez l’ordre et les labels manquants avec
sortetdropna. - Priorisez les méthodes vectorisées pour garder des pipelines rapides.