Module 4
Consolidation et Maîtrise de Pandas
Allez au-delà des bases en apprenant les techniques avancées pour répondre à des questions complexes, combiner des sources de données et nettoyer des données imparfaites.
4.1. Agrégation de Données avec groupby()
Pour répondre à des questions comme "Quel est le salaire moyen par département ?", on utilise la méthode groupby(). Elle suit une logique en 3 étapes : Split-Apply-Combine (Diviser-Appliquer-Combiner).
- Split : Le DataFrame est divisé en sous-groupes basés sur les valeurs d'une colonne.
- Apply : Une fonction (comme .mean(), .sum(), .count()) est appliquée à chaque sous-groupe.
- Combine : Les résultats sont rassemblés dans un nouveau DataFrame.
import pandas as pd
data = {
'Nom': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
'Département': ['IT', 'RH', 'IT', 'RH', 'IT', 'Marketing'],
'Salaire': [75000, 55000, 82000, 60000, 90000, 68000]
}
df = pd.DataFrame(data)
# Calculons le salaire moyen par département
salaire_moyen_par_dept = df.groupby('Département')['Salaire'].mean()
print("Salaire moyen par département:\n", salaire_moyen_par_dept)
# Comptons le nombre d'employés par département
effectifs = df.groupby('Département').size()
print("\nEffectifs par département:\n", effectifs)
4.2. Combiner des Données : merge et concat
Les données réelles sont rarement dans un seul fichier. Savoir les combiner est une compétence essentielle.
pd.merge() : La Jointure Intelligente
Utilisez merge() lorsque vous souhaitez combiner des DataFrames qui ont une colonne en commun (une "clé"). C'est l'équivalent des JOIN en SQL.
# DataFrame 1: Les employés
employes = pd.DataFrame({
'employee_id': [1, 2, 3, 4],
'nom': ['Alice', 'Bob', 'Charlie', 'David'],
'dept_id': [101, 102, 101, 103]
})
# DataFrame 2: Les départements
departements = pd.DataFrame({
'dept_id': [101, 102, 103],
'dept_nom': ['IT', 'RH', 'Marketing']
})
# Fusionnons les deux sur la clé 'dept_id'
df_complet = pd.merge(employes, departements, on='dept_id')
print(df_complet)
pd.concat() : L'Empilement Brut
Utilisez concat() lorsque vous voulez empiler des DataFrames les uns sur les autres (concaténation de lignes). Les colonnes doivent être similaires.
ventes_jan = pd.DataFrame({'produit': ['A', 'B'], 'quantite': [100, 150]})
ventes_fev = pd.DataFrame({'produit': ['A', 'C'], 'quantite': [120, 50]})
# Empilons les deux DataFrames
ventes_totales = pd.concat([ventes_jan, ventes_fev], ignore_index=True)
print(ventes_totales)
4.3. Nettoyage de Données Avancé
Les données du monde réel sont "sales". Elles contiennent des doublons, des erreurs de frappe, des formats incohérents...
Gestion des Doublons
data_doublons = {'col1': ['A', 'B', 'A'], 'col2': [1, 2, 1]}
df_doublons = pd.DataFrame(data_doublons)
print("Avec doublons:\n", df_doublons)
# Supprimer les lignes dupliquées
df_sans_doublons = df_doublons.drop_duplicates(ignore_index=True)
print("\nSans doublons:\n", df_sans_doublons)
Travailler avec du Texte (.str)
L'accesseur .str donne accès à toutes les méthodes de chaînes de caractères de Python, mais appliquées à une Series entière.
df_texte = pd.DataFrame({'ville': [' Paris', 'Londres ', ' new york ']})
# Standardiser les noms de ville
df_texte['ville_propre'] = df_texte['ville'].str.strip().str.capitalize()
print(df_texte)
Gérer les Dates et Heures (.dt)
Les dates sont souvent lues comme du texte. pd.to_datetime les convertit, et l'accesseur .dt permet d'en extraire des informations.
df_dates = pd.DataFrame({'date_str': ['2025-01-15', '2025-02-28']})
# 1. Convertir la colonne en format datetime
df_dates['date'] = pd.to_datetime(df_dates['date_str'])
# 2. Extraire des informations avec .dt
df_dates['annee'] = df_dates['date'].dt.year
df_dates['nom_jour'] = df_dates['date'].dt.day_name()
print(df_dates)
Exercices Pratiques
Exercice 1 : Agrégation Multiple avec `groupby()`
En utilisant le DataFrame des employés de la section 4.1, calculez pour chaque département non seulement le salaire moyen, mais aussi le salaire maximum et le nombre total d'employés. Affichez le résultat dans un seul DataFrame.
Voir la solution
import pandas as pd
data = {
'Nom': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
'Département': ['IT', 'RH', 'IT', 'RH', 'IT', 'Marketing'],
'Salaire': [75000, 55000, 82000, 60000, 90000, 68000]
}
df = pd.DataFrame(data)
# On utilise .agg() pour appliquer plusieurs fonctions d'agrégation
stats_par_dept = df.groupby('Département')['Salaire'].agg(['mean', 'max', 'count'])
# On renomme les colonnes pour plus de clarté
stats_par_dept.columns = ['Salaire Moyen', 'Salaire Max', 'Nombre Employés']
print(stats_par_dept)
Exercice 2 : Fusionner des Données Clients et Commandes
Vous avez deux DataFrames : un avec des informations sur les clients, et un autre avec leurs commandes. Fusionnez ces deux tables pour obtenir un DataFrame qui contient le nom du client à côté de chaque commande.
clients = pd.DataFrame({
'client_id': [1, 2, 3],
'nom': ['Alice', 'Bob', 'Charlie']
})
commandes = pd.DataFrame({
'commande_id': [101, 102, 103, 104],
'client_id': [2, 1, 2, 3],
'montant': [150, 200, 50, 300]
})
Voir la solution
import pandas as pd
clients = pd.DataFrame({
'client_id': [1, 2, 3],
'nom': ['Alice', 'Bob', 'Charlie']
})
commandes = pd.DataFrame({
'commande_id': [101, 102, 103, 104],
'client_id': [2, 1, 2, 3],
'montant': [150, 200, 50, 300]
})
# On fusionne les deux DataFrames sur la colonne commune 'client_id'
donnees_fusionnees = pd.merge(commandes, clients, on='client_id')
print(donnees_fusionnees)
Exercice 3 : Nettoyage de Données Textuelles
Vous recevez un DataFrame avec une colonne 'email' qui contient des données mal formatées (espaces inutiles, casse incohérente). Nettoyez cette colonne en retirant les espaces au début et à la fin, et en mettant tout en minuscules.
data_emails = {'email': [' Alice@Example.com ', 'BOB@EMAIL.COM', ' charlie@domain.org']}
df_emails = pd.DataFrame(data_emails)
Voir la solution
import pandas as pd
data_emails = {'email': [' Alice@Example.com ', 'BOB@EMAIL.COM', ' charlie@domain.org']}
df_emails = pd.DataFrame(data_emails)
# On enchaîne les méthodes de l'accesseur .str
df_emails['email_propre'] = df_emails['email'].str.strip().str.lower()
print(df_emails)