🔝 Retour au Sommaire
L'une des opérations les plus puissantes dans l'analyse de données est la capacité de regrouper des données et d'effectuer des calculs par groupe. Par exemple :
- Calculer les ventes totales par ville
- Trouver la moyenne des notes par classe
- Compter le nombre de clients par catégorie
Pandas offre la méthode groupby() qui permet d'effectuer ces opérations facilement et efficacement.
import pandas as pd
import numpy as np La méthode groupby() suit un paradigme en trois étapes appelé Split-Apply-Combine :
- Split (Diviser) : Les données sont divisées en groupes selon un critère
- Apply (Appliquer) : Une fonction est appliquée indépendamment à chaque groupe
- Combine (Combiner) : Les résultats sont combinés en une structure de données
# Visualisation conceptuelle
#
# Données originales:
# Ville Ventes
# 0 Paris 100
# 1 Lyon 150
# 2 Paris 120
# 3 Lyon 180
#
# SPLIT par Ville:
# Groupe Paris: [100, 120]
# Groupe Lyon: [150, 180]
#
# APPLY (somme):
# Paris: 220
# Lyon: 330
#
# COMBINE:
# Ville
# Lyon 330
# Paris 220# Créer un DataFrame d'exemple
df = pd.DataFrame({
'Ville': ['Paris', 'Lyon', 'Paris', 'Lyon', 'Marseille', 'Paris'],
'Produit': ['A', 'A', 'B', 'B', 'A', 'A'],
'Ventes': [100, 150, 120, 180, 90, 110],
'Quantité': [5, 8, 6, 9, 4, 5]
})
print("DataFrame original:")
print(df)
# Grouper par ville et calculer la somme
ventes_par_ville = df.groupby('Ville')['Ventes'].sum()
print("\nVentes totales par ville:")
print(ventes_par_ville) Sortie :
Ville
Lyon 330
Marseille 90
Paris 330
Name: Ventes, dtype: int64
# Créer un objet GroupBy
groupe = df.groupby('Ville')
print("Type de l'objet:", type(groupe))
print("Nombre de groupes:", groupe.ngroups)
print("Noms des groupes:", list(groupe.groups.keys()))
# Voir le contenu de chaque groupe
print("\nContenu des groupes:")
for nom, groupe_df in groupe:
print(f"\n--- Groupe: {nom} ---")
print(groupe_df)# Obtenir un groupe spécifique
groupe_paris = df.groupby('Ville').get_group('Paris')
print("Groupe Paris:")
print(groupe_paris) df = pd.DataFrame({
'Catégorie': ['A', 'B', 'A', 'B', 'A'],
'Ventes': [100, 150, 120, 180, 90],
'Quantité': [5, 8, 6, 9, 4]
})
# Somme des ventes par catégorie
print("Somme par catégorie:")
print(df.groupby('Catégorie')['Ventes'].sum())
# Somme sur toutes les colonnes numériques
print("\nSomme sur toutes les colonnes:")
print(df.groupby('Catégorie').sum()) # Moyenne des ventes par catégorie
print("Moyenne par catégorie:")
print(df.groupby('Catégorie')['Ventes'].mean()) # Compter le nombre d'entrées par catégorie
print("Nombre d'entrées par catégorie:")
print(df.groupby('Catégorie')['Ventes'].count())
# Alternative : size() compte aussi les valeurs NaN
print("\nAvec size():")
print(df.groupby('Catégorie').size()) # Minimum et maximum par catégorie
print("Ventes minimales par catégorie:")
print(df.groupby('Catégorie')['Ventes'].min())
print("\nVentes maximales par catégorie:")
print(df.groupby('Catégorie')['Ventes'].max()) # Écart-type des ventes par catégorie
print("Écart-type par catégorie:")
print(df.groupby('Catégorie')['Ventes'].std())
# Variance
print("\nVariance par catégorie:")
print(df.groupby('Catégorie')['Ventes'].var()) # Médiane des ventes par catégorie
print("Médiane par catégorie:")
print(df.groupby('Catégorie')['Ventes'].median()) df = pd.DataFrame({
'Ville': ['Paris', 'Lyon', 'Paris', 'Lyon', 'Marseille'],
'Produit': ['A', 'A', 'B', 'B', 'A'],
'Ventes': [100, 150, 120, 180, 90],
'Quantité': [5, 8, 6, 9, 4]
})
# Calculer la somme de plusieurs colonnes
resultat = df.groupby('Ville')[['Ventes', 'Quantité']].sum()
print("Somme des ventes et quantités par ville:")
print(resultat) # Appliquer plusieurs fonctions d'agrégation
stats = df.groupby('Ville')['Ventes'].agg(['sum', 'mean', 'min', 'max', 'count'])
print("Statistiques des ventes par ville:")
print(stats) # Agrégations personnalisées par colonne
resultat = df.groupby('Ville').agg({
'Ventes': ['sum', 'mean'],
'Quantité': ['sum', 'max']
})
print("Agrégations personnalisées:")
print(resultat) # Utiliser des noms personnalisés pour les colonnes
resultat = df.groupby('Ville').agg(
Ventes_totales=('Ventes', 'sum'),
Ventes_moyennes=('Ventes', 'mean'),
Quantité_totale=('Quantité', 'sum'),
Quantité_max=('Quantité', 'max')
)
print("Avec noms personnalisés:")
print(resultat) # Définir une fonction personnalisée
def etendue(serie):
"""Calcule l'étendue (max - min)"""
return serie.max() - serie.min()
# Appliquer la fonction personnalisée
resultat = df.groupby('Ville')['Ventes'].agg(['mean', etendue])
print("Avec fonction personnalisée:")
print(resultat)
# Fonction lambda
resultat = df.groupby('Ville')['Ventes'].agg(
moyenne='mean',
coefficient_variation=lambda x: x.std() / x.mean()
)
print("\nAvec lambda:")
print(resultat) df = pd.DataFrame({
'Région': ['Nord', 'Nord', 'Sud', 'Sud', 'Nord', 'Sud'],
'Ville': ['Paris', 'Lyon', 'Marseille', 'Toulouse', 'Paris', 'Marseille'],
'Produit': ['A', 'A', 'A', 'B', 'B', 'B'],
'Ventes': [100, 150, 90, 120, 110, 130]
})
print("DataFrame original:")
print(df)
# Grouper par Région et Ville
ventes_region_ville = df.groupby(['Région', 'Ville'])['Ventes'].sum()
print("\nVentes par Région et Ville:")
print(ventes_region_ville)
# Avec plusieurs colonnes et agrégations
stats = df.groupby(['Région', 'Ville']).agg({
'Ventes': ['sum', 'mean'],
'Produit': 'count'
})
print("\nStatistiques détaillées:")
print(stats) # Le résultat a un MultiIndex, on peut le réinitialiser
ventes_df = df.groupby(['Région', 'Ville'])['Ventes'].sum().reset_index()
print("Avec index réinitialisé:")
print(ventes_df) # Grouper et trier par la valeur agrégée
ventes_triees = (df.groupby(['Région', 'Ville'])['Ventes']
.sum()
.sort_values(ascending=False)
.reset_index())
print("Trié par ventes décroissantes:")
print(ventes_triees) La méthode transform() applique une fonction et retourne un résultat de la même taille que l'entrée.
df = pd.DataFrame({
'Ville': ['Paris', 'Lyon', 'Paris', 'Lyon', 'Paris'],
'Ventes': [100, 150, 120, 180, 90]
})
print("DataFrame original:")
print(df)
# Calculer la moyenne par ville et l'ajouter comme colonne
df['Moyenne_ville'] = df.groupby('Ville')['Ventes'].transform('mean')
print("\nAvec moyenne par ville:")
print(df)
# Normaliser par rapport à la moyenne du groupe
df['Ventes_normalisées'] = (df['Ventes'] - df['Moyenne_ville']) / df.groupby('Ville')['Ventes'].transform('std')
print("\nAvec ventes normalisées:")
print(df)
# Fonction personnalisée avec transform
df['Rang_dans_ville'] = df.groupby('Ville')['Ventes'].transform(lambda x: x.rank(method='dense'))
print("\nAvec rang dans chaque ville:")
print(df) La méthode filter() permet de conserver ou supprimer des groupes entiers selon une condition.
df = pd.DataFrame({
'Ville': ['Paris', 'Lyon', 'Paris', 'Lyon', 'Marseille', 'Paris'],
'Ventes': [100, 150, 120, 180, 50, 90]
})
print("DataFrame original:")
print(df)
# Garder seulement les villes avec des ventes totales > 200
villes_importantes = df.groupby('Ville').filter(lambda x: x['Ventes'].sum() > 200)
print("\nVilles avec ventes totales > 200:")
print(villes_importantes)
# Garder les villes avec au moins 3 entrées
villes_frequentes = df.groupby('Ville').filter(lambda x: len(x) >= 3)
print("\nVilles avec au moins 3 entrées:")
print(villes_frequentes) La méthode apply() est la plus flexible et permet d'appliquer n'importe quelle fonction à chaque groupe.
df = pd.DataFrame({
'Catégorie': ['A', 'A', 'B', 'B', 'A', 'B'],
'Valeur': [10, 15, 20, 25, 12, 22]
})
print("DataFrame original:")
print(df)
# Fonction simple
def calcul_range(groupe):
return groupe['Valeur'].max() - groupe['Valeur'].min()
etendue = df.groupby('Catégorie').apply(calcul_range)
print("\nÉtendue par catégorie:")
print(etendue)
# Retourner un DataFrame
def stats_groupe(groupe):
return pd.Series({
'min': groupe['Valeur'].min(),
'max': groupe['Valeur'].max(),
'etendue': groupe['Valeur'].max() - groupe['Valeur'].min()
})
stats = df.groupby('Catégorie').apply(stats_groupe)
print("\nStatistiques par catégorie:")
print(stats)
# Opération plus complexe : normalisation par groupe
def normaliser(groupe):
groupe['Valeur_norm'] = (groupe['Valeur'] - groupe['Valeur'].mean()) / groupe['Valeur'].std()
return groupe
df_norm = df.groupby('Catégorie').apply(normaliser)
print("\nAvec valeurs normalisées par groupe:")
print(df_norm) # DataFrame avec MultiIndex
arrays = [
['A', 'A', 'B', 'B'],
['X', 'Y', 'X', 'Y']
]
index = pd.MultiIndex.from_arrays(arrays, names=['Groupe', 'Sous-groupe'])
df = pd.DataFrame({'Valeur': [10, 20, 30, 40]}, index=index)
print("DataFrame avec MultiIndex:")
print(df)
# Grouper par niveau d'index
par_groupe = df.groupby(level='Groupe')['Valeur'].sum()
print("\nSomme par Groupe:")
print(par_groupe)
par_sous_groupe = df.groupby(level='Sous-groupe')['Valeur'].sum()
print("\nSomme par Sous-groupe:")
print(par_sous_groupe) df = pd.DataFrame({
'Date': pd.date_range('2024-01-01', periods=10, freq='D'),
'Ventes': [100, 120, 90, 110, 130, 95, 105, 115, 125, 100]
})
df.set_index('Date', inplace=True)
print("DataFrame avec dates:")
print(df)
# Grouper par mois
par_mois = df.groupby(df.index.month)['Ventes'].sum()
print("\nVentes par mois:")
print(par_mois)
# Grouper par jour de la semaine
par_jour = df.groupby(df.index.dayofweek)['Ventes'].mean()
print("\nVentes moyennes par jour de la semaine:")
print(par_jour) df = pd.DataFrame({
'Catégorie': ['A', 'A', 'B', 'B', 'A', 'B'],
'Valeur': [10, np.nan, 20, 25, 15, np.nan]
})
print("DataFrame avec NaN:")
print(df)
# Les agrégations ignorent les NaN par défaut
print("\nMoyenne par catégorie (ignore NaN):")
print(df.groupby('Catégorie')['Valeur'].mean())
# Compter en excluant les NaN
print("\nCompte (sans NaN):")
print(df.groupby('Catégorie')['Valeur'].count())
# Compter tous les éléments (avec NaN)
print("\nCompte total (avec NaN):")
print(df.groupby('Catégorie')['Valeur'].size())
# Somme (NaN devient 0)
print("\nSomme par catégorie:")
print(df.groupby('Catégorie')['Valeur'].sum()) # Données de ventes
ventes = pd.DataFrame({
'Date': pd.date_range('2024-01-01', periods=12, freq='MS'),
'Région': ['Nord', 'Sud', 'Est', 'Ouest'] * 3,
'Produit': ['A', 'A', 'B', 'B'] * 3,
'Ventes': [1000, 1200, 800, 900, 1100, 1300, 850, 950, 1050, 1250, 900, 1000],
'Quantité': [50, 60, 40, 45, 55, 65, 42, 48, 52, 62, 45, 50]
})
print("Données de ventes:")
print(ventes.head())
# 1. Ventes totales par région
print("\n--- Ventes totales par région ---")
ventes_region = ventes.groupby('Région')['Ventes'].sum().sort_values(ascending=False)
print(ventes_region)
# 2. Statistiques par produit
print("\n--- Statistiques par produit ---")
stats_produit = ventes.groupby('Produit').agg({
'Ventes': ['sum', 'mean', 'min', 'max'],
'Quantité': ['sum', 'mean']
})
print(stats_produit)
# 3. Performance par région et produit
print("\n--- Performance par région et produit ---")
perf = ventes.groupby(['Région', 'Produit']).agg(
Ventes_totales=('Ventes', 'sum'),
Ventes_moyennes=('Ventes', 'mean'),
Quantité_totale=('Quantité', 'sum')
).reset_index()
print(perf)
# 4. Trouver la meilleure région pour chaque produit
print("\n--- Meilleure région par produit ---")
meilleures = (ventes.groupby(['Produit', 'Région'])['Ventes']
.sum()
.reset_index()
.sort_values('Ventes', ascending=False)
.groupby('Produit')
.first())
print(meilleures)
# 5. Pourcentage des ventes par région
print("\n--- Pourcentage des ventes par région ---")
total_ventes = ventes['Ventes'].sum()
pct_region = (ventes.groupby('Région')['Ventes'].sum() / total_ventes * 100).round(2)
print(pct_region) # Données d'étudiants
notes = pd.DataFrame({
'Étudiant': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob', 'Charlie'] * 2,
'Matière': ['Math', 'Math', 'Math', 'Physique', 'Physique', 'Physique'] * 2,
'Trimestre': ['T1', 'T1', 'T1', 'T1', 'T1', 'T1', 'T2', 'T2', 'T2', 'T2', 'T2', 'T2'],
'Note': [15, 12, 18, 13, 14, 16, 16, 13, 17, 14, 15, 18]
})
print("Données de notes:")
print(notes)
# 1. Moyenne par étudiant
print("\n--- Moyenne générale par étudiant ---")
moy_etudiant = notes.groupby('Étudiant')['Note'].mean().round(2)
print(moy_etudiant)
# 2. Moyenne par matière
print("\n--- Moyenne par matière ---")
moy_matiere = notes.groupby('Matière')['Note'].mean().round(2)
print(moy_matiere)
# 3. Évolution par étudiant et matière
print("\n--- Évolution par étudiant et matière ---")
evolution = notes.groupby(['Étudiant', 'Matière', 'Trimestre'])['Note'].mean().unstack()
print(evolution)
# 4. Meilleure et moins bonne note par étudiant
print("\n--- Min et Max par étudiant ---")
minmax = notes.groupby('Étudiant')['Note'].agg(['min', 'max', 'mean'])
print(minmax)
# 5. Classement des étudiants
print("\n--- Classement des étudiants ---")
classement = (notes.groupby('Étudiant')['Note']
.mean()
.sort_values(ascending=False)
.reset_index()
.rename(columns={'Note': 'Moyenne'}))
classement['Rang'] = range(1, len(classement) + 1)
print(classement)
# 6. Progression entre T1 et T2
print("\n--- Progression T1 -> T2 ---")
notes_pivot = notes.pivot_table(values='Note',
index='Étudiant',
columns='Trimestre',
aggfunc='mean')
notes_pivot['Progression'] = notes_pivot['T2'] - notes_pivot['T1']
print(notes_pivot) # Données de commandes
commandes = pd.DataFrame({
'Date': pd.date_range('2024-01-01', periods=20, freq='D'),
'Client': ['Client_A', 'Client_B', 'Client_A', 'Client_C'] * 5,
'Catégorie': ['Électronique', 'Vêtements', 'Électronique', 'Livres'] * 5,
'Montant': np.random.randint(50, 500, 20),
'Produits': np.random.randint(1, 10, 20)
})
print("Données de commandes:")
print(commandes.head(10))
# 1. Chiffre d'affaires par client
print("\n--- CA par client ---")
ca_client = (commandes.groupby('Client')['Montant']
.sum()
.sort_values(ascending=False)
.reset_index()
.rename(columns={'Montant': 'CA_total'}))
print(ca_client)
# 2. Panier moyen par catégorie
print("\n--- Panier moyen par catégorie ---")
panier_moy = commandes.groupby('Catégorie').agg(
Montant_moyen=('Montant', 'mean'),
Montant_total=('Montant', 'sum'),
Nb_commandes=('Montant', 'count')
).round(2)
print(panier_moy)
# 3. Fréquence d'achat par client
print("\n--- Fréquence d'achat ---")
freq = commandes.groupby('Client').agg(
Nb_commandes=('Date', 'count'),
Première_commande=('Date', 'min'),
Dernière_commande=('Date', 'max')
)
freq['Jours_entre_commandes'] = (freq['Dernière_commande'] - freq['Première_commande']).dt.days / freq['Nb_commandes']
print(freq)
# 4. Top 3 des catégories par client
print("\n--- Top catégories par client ---")
top_cat = (commandes.groupby(['Client', 'Catégorie'])['Montant']
.sum()
.reset_index()
.sort_values(['Client', 'Montant'], ascending=[True, False])
.groupby('Client')
.head(2))
print(top_cat)
# 5. Analyse temporelle : CA par semaine
commandes['Semaine'] = commandes['Date'].dt.isocalendar().week
print("\n--- CA par semaine ---")
ca_semaine = commandes.groupby('Semaine')['Montant'].sum()
print(ca_semaine) # Données d'employés
employes = pd.DataFrame({
'Nom': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Henry'],
'Département': ['IT', 'Ventes', 'IT', 'RH', 'Ventes', 'IT', 'RH', 'Ventes'],
'Poste': ['Dev', 'Manager', 'Dev', 'Recrut', 'Vendeur', 'Manager', 'Recrut', 'Vendeur'],
'Salaire': [45000, 55000, 48000, 40000, 38000, 65000, 42000, 40000],
'Ancienneté': [2, 5, 3, 4, 1, 8, 6, 2]
})
print("Données employés:")
print(employes)
# 1. Salaire moyen par département
print("\n--- Salaire moyen par département ---")
sal_dept = employes.groupby('Département')['Salaire'].mean().round(2)
print(sal_dept)
# 2. Statistiques complètes par département
print("\n--- Statistiques par département ---")
stats_dept = employes.groupby('Département').agg({
'Salaire': ['mean', 'min', 'max', 'std'],
'Ancienneté': 'mean',
'Nom': 'count'
}).round(2)
stats_dept.columns = ['Sal_moyen', 'Sal_min', 'Sal_max', 'Sal_std', 'Anc_moy', 'Effectif']
print(stats_dept)
# 3. Masse salariale par département
print("\n--- Masse salariale ---")
masse_sal = employes.groupby('Département').agg(
Masse_salariale=('Salaire', 'sum'),
Effectif=('Nom', 'count')
)
masse_sal['Salaire_moyen'] = masse_sal['Masse_salariale'] / masse_sal['Effectif']
print(masse_sal)
# 4. Salaire moyen par poste et département
print("\n--- Salaire par poste et département ---")
sal_poste = employes.groupby(['Département', 'Poste'])['Salaire'].mean().unstack()
print(sal_poste)
# 5. Identifier les salaires au-dessus de la moyenne du département
print("\n--- Employés au-dessus de la moyenne ---")
employes['Salaire_moy_dept'] = employes.groupby('Département')['Salaire'].transform('mean')
employes['Au_dessus_moy'] = employes['Salaire'] > employes['Salaire_moy_dept']
print(employes[['Nom', 'Département', 'Salaire', 'Salaire_moy_dept', 'Au_dessus_moy']])
# 6. Top 2 salaires par département
print("\n--- Top 2 salaires par département ---")
top_salaires = (employes.sort_values('Salaire', ascending=False)
.groupby('Département')
.head(2)[['Nom', 'Département', 'Salaire']])
print(top_salaires)# Données de capteurs
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=24, freq='h')
capteurs = pd.DataFrame({
'DateTime': list(dates) * 2,
'Capteur': ['Temp_1'] * 24 + ['Temp_2'] * 24,
'Température': np.random.normal(20, 3, 48),
'Humidité': np.random.normal(60, 10, 48)
})
print("Données capteurs:")
print(capteurs.head(10))
# 1. Moyenne quotidienne par capteur
capteurs['Date'] = capteurs['DateTime'].dt.date
print("\n--- Moyenne quotidienne ---")
moy_jour = capteurs.groupby(['Date', 'Capteur']).agg({
'Température': 'mean',
'Humidité': 'mean'
}).round(2)
print(moy_jour.head(10))
# 2. Min, Max, Moyenne par capteur
print("\n--- Statistiques par capteur ---")
stats = capteurs.groupby('Capteur').agg({
'Température': ['min', 'max', 'mean', 'std'],
'Humidité': ['min', 'max', 'mean', 'std']
}).round(2)
print(stats)
# 3. Heures avec température > 22°C
print("\n--- Heures chaudes par capteur ---")
capteurs['Chaud'] = capteurs['Température'] > 22
heures_chaudes = capteurs.groupby('Capteur')['Chaud'].sum()
print(heures_chaudes)
# 4. Plage horaire : moyenne par heure de la journée
capteurs['Heure'] = capteurs['DateTime'].dt.hour
print("\n--- Température moyenne par heure ---")
temp_heure = capteurs.groupby('Heure')['Température'].mean().round(2)
print(temp_heure)
# 5. Écart entre les deux capteurs
print("\n--- Écart entre capteurs ---")
temp_pivot = capteurs.pivot_table(values='Température',
index='DateTime',
columns='Capteur')
temp_pivot['Écart'] = abs(temp_pivot['Temp_1'] - temp_pivot['Temp_2'])
print("\nÉcart moyen:", temp_pivot['Écart'].mean().round(2))
print("Écart maximum:", temp_pivot['Écart'].max().round(2)) # Créer des groupes d'âge
df = pd.DataFrame({
'Nom': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
'Âge': [23, 35, 28, 45, 31, 52],
'Salaire': [35000, 45000, 40000, 55000, 42000, 60000]
})
print("DataFrame original:")
print(df)
# Créer des tranches d'âge
df['Tranche_âge'] = pd.cut(df['Âge'], bins=[20, 30, 40, 60], labels=['20-30', '30-40', '40-60'])
print("\nAvec tranches d'âge:")
print(df)
# Analyser par tranche
print("\nSalaire moyen par tranche d'âge:")
print(df.groupby('Tranche_âge')['Salaire'].mean()) # Grouper selon une condition
df = pd.DataFrame({
'Produit': ['A', 'B', 'C', 'D', 'E'],
'Prix': [10, 25, 15, 45, 20]
})
# Créer des groupes personnalisés
def categoriser_prix(prix):
if prix < 20:
return 'Économique'
elif prix < 40:
return 'Standard'
else:
return 'Premium'
df['Catégorie'] = df['Prix'].apply(categoriser_prix)
print("Produits catégorisés:")
print(df)
print("\nNombre de produits par catégorie:")
print(df.groupby('Catégorie').size()) # Moyenne mobile par groupe
df = pd.DataFrame({
'Date': pd.date_range('2024-01-01', periods=10),
'Ville': ['Paris', 'Lyon'] * 5,
'Ventes': [100, 120, 110, 130, 105, 125, 115, 135, 120, 140]
})
print("DataFrame original:")
print(df)
# Moyenne mobile sur 3 jours par ville
df = df.sort_values(['Ville', 'Date'])
df['Moyenne_mobile'] = df.groupby('Ville')['Ventes'].transform(lambda x: x.rolling(3, min_periods=1).mean())
print("\nAvec moyenne mobile:")
print(df) # ✅ Bon : utiliser agg() pour plusieurs agrégations
stats = df.groupby('Catégorie').agg({
'Ventes': ['sum', 'mean'],
'Quantité': 'sum'
})
# ❌ Moins efficace : chaîner plusieurs opérations
# somme = df.groupby('Catégorie')['Ventes'].sum()
# moyenne = df.groupby('Catégorie')['Ventes'].mean()# ✅ Bon : résultat sous forme de DataFrame
resultat = df.groupby('Ville')['Ventes'].sum().reset_index()
# Plus facile à manipuler et à visualiser
# ❌ Moins pratique : Series avec index
# resultat = df.groupby('Ville')['Ventes'].sum()# ✅ Bon : noms explicites
resultat = df.groupby('Ville').agg(
Total_ventes=('Ventes', 'sum'),
Ventes_moyennes=('Ventes', 'mean'),
Nb_transactions=('Ventes', 'count')
)
# ❌ Moins clair
# resultat = df.groupby('Ville')['Ventes'].agg(['sum', 'mean', 'count'])# ✅ Bon : vérifier les groupes
print("Nombre de groupes:", df.groupby('Catégorie').ngroups)
print("Groupes:", list(df.groupby('Catégorie').groups.keys()))
# Puis agréger
resultat = df.groupby('Catégorie')['Ventes'].sum()# ✅ Bon : gérer explicitement les NaN
# Option 1 : Nettoyer avant groupby
df_clean = df.dropna(subset=['Catégorie', 'Ventes'])
resultat = df_clean.groupby('Catégorie')['Ventes'].sum()
# Option 2 : Inclure les NaN comme groupe
resultat = df.groupby('Catégorie', dropna=False)['Ventes'].sum()GroupBy et les agrégations sont des outils essentiels pour l'analyse de données avec Pandas. Voici les points clés à retenir :
Concept de base :
- Split-Apply-Combine : diviser, appliquer, combiner
groupby()crée des groupes selon un ou plusieurs critères
Fonctions d'agrégation principales :
sum(),mean(),count(),min(),max()std(),var(),median()agg()pour agrégations multiples et personnalisées
Méthodes avancées :
transform(): opérations en gardant la forme originalefilter(): filtrer des groupes entiersapply(): maximum de flexibilité
Groupements :
- Simple : une colonne
- Multiple : plusieurs colonnes (MultiIndex)
- Par index, par fonction, par bins
Bonnes pratiques :
- Utiliser
agg()pour plusieurs agrégations - Nommer les colonnes agrégées pour plus de clarté
- Utiliser
reset_index()pour des DataFrames plus maniables - Vérifier les groupes avant d'agréger
- Gérer explicitement les valeurs manquantes
GroupBy est particulièrement utile pour :
- Analyses comparatives entre groupes
- Calculs de statistiques par catégorie
- Transformations par groupe
- Filtrage de groupes selon des critères
La maîtrise de GroupBy vous permettra d'effectuer des analyses de données complexes de manière efficace et élégante.