A la fin de ce laboratoire, vous saurez : 1. Identifier les problemes de qualite dans un jeu de données (valeurs manquantes, types incorrects) 2. Appliquer des stratégies de nettoyage appropriees (dropna, fillna, imputation intelligente) 3. Transformer et enrichir les données (conversion de types, creation de colonnes) 4. Effectuer des agregations pour repondre a des questions metier
Prerequis
Python 3.10+
Connaissance de base de Pandas
Fichier transactions.csv dans le repertoire courant
Duree estimee : 30-45 minutes
Introduction : La Règle des 80/20 en Data Science
En Data Science, on dit souvent que 80% du temps est consacré à la préparation et au nettoyage des données, et seulement 20% à l’analyse et à la modélisation. Cette étape, bien que moins glamour, est absolument cruciale. Des données de mauvaise qualité mènent inévitablement à des modèles et des conclusions de mauvaise qualité (‘Garbage In, Garbage Out’).
Dans ce laboratoire, nous allons aborder de front ce travail de préparation en utilisant un jeu de données volontairement “sale”.
Origine de la règle. Cette statistique provient du CrowdFlower Data Science Report (2016), une enquête auprès de data scientists popularisée par la presse spécialisée (Forbes, 2016) : environ 80% du temps de travail est consacré à la collecte, au nettoyage et à l’organisation des données, contre ~20% à la modélisation et l’analyse. Elle souligne l’importance — et la rentabilité — des compétences en data wrangling.
Étape 1 : Inspection des Données
Avant de corriger quoi que ce soit, il faut diagnostiquer. L’inspection répond à trois questions qui conditionnent tout le reste : quelles colonnes existent et dans quel type (un prix stocké en texte empêchera toute agrégation), combien de valeurs manquent et où, et quelles anomalies visuelles apparaissent déjà (df.head()). Sauter cette étape mène à des nettoyages aveugles — par exemple imputer des valeurs sans avoir remarqué qu’une colonne entière est corrompue.
import pandas as pdfrom pathlib import Path# Resolution robuste : CWD = repertoire du notebook (Jupyter classique)# OU parent contenant le chemin du notebook (Papermill depuis le depot)._data = Path('transactions.csv')ifnot _data.exists():for _p in [Path.cwd(), *Path.cwd().parents]: _candidate = _p /'MyIA.AI.Notebooks/ML/DataScienceWithAgents/Track1-LangChain/Day3-Data-Agents/Labs/Lab4-DataWrangling'/'transactions.csv'if _candidate.exists(): _data = _candidatebreak# Charger le jeu de donneesdf = pd.read_csv(_data)# Afficher les premieres lignesdf.head()
date
id_produit
categorie
quantite
prix_unitaire
0
2023-10-01
A101
Electronique
5.0
120.0
1
2023-10-01
B202
Livre
10.0
15.5
2
2023-10-02
A101
Electronique
3.0
NaN
3
2023-10-03
C303
Maison
2.0
75.9
4
2023-10-03
B202
Livre
6.0
15.5
Vue d’ensemble de la structure
Après avoir examine les premières lignes, explorons la structure globale du DataFrame : types de colonnes, nombre de valeurs non-nulles, et memoire utilisee. Cette étape nous revelera les problemes potentiels (types incorrects, valeurs manquantes).
# Obtenir un résumé des informations du DataFramedf.info()
Maintenant, comptabilisons précisément les valeurs manquantes par colonne. Cela nous permettra de prioriser les actions de nettoyage et de choisir la stratégie appropriee (suppression, imputation, etc.).
# Compter les valeurs manquantes par colonnedf.isnull().sum()
Observations : Exécutez les cellules ci-dessus, puis notez vos observations : - Quel est le type de la colonne date ? Devrait-elle être convertie ? - Combien de valeurs manquantes y a-t-il dans chaque colonne ? - Quelles colonnes semblent avoir des types incorrects ?
Étape 2 : Nettoyage - Gestion des Valeurs Manquantes
Les valeurs manquantes (NaN) ne se traitent pas toutes pareil : une ligne incomplète peut être supprimée (une transaction sans quantité n’a pas de sens métier), tandis qu’une cellule isolée appelle souvent une imputation. Le choix dépend du coût d’une erreur : supprimer réduit le volume de données, imputer risque d’introduire un biais. Ici on combine les deux — dropna pour la quantité, puis une imputation « intelligente » (moyenne par produit) qui préserve la cohérence économique plutôt qu’une moyenne globale brutale.
# Supprimer les lignes où la quantité est manquante# Une transaction sans quantité n'est pas exploitabledf.dropna(subset=['quantite'], inplace=True)print(f"Lignes restantes apres suppression des quantites manquantes : {len(df)}")
Lignes restantes apres suppression des quantites manquantes : 6
Imputation intelligente des prix manquants
Pour les prix unitaires manquants, nous allons utiliser une stratégie d’imputation plus sophistiquee que la simple moyenne globale : nous remplacerons chaque valeur manquante par la moyenne des prix du même produit. Cette approche preserve mieux la coherence economique des données.
# Remplir le prix manquant avec la moyenne des prix du même produit# C'est une stratégie d'imputation plus intelligente que la moyenne globaledf['prix_unitaire'] = df.groupby('id_produit')['prix_unitaire'].transform(lambda x: x.fillna(x.mean()))# Vérifions s'il reste des valeurs nullesdf.isnull().sum()
Pourquoi maintenant, après le nettoyage ? Parce que convertir le type d’une colonne truffée de NaN produit des erreurs ou des valeurs sentinelles (NaT) qu’il faut ensuite retraiter. Une fois les manques comblés, on peut convertir sereinement — typiquement les date lues en str par read_csv vers un vrai datetime, ce qui débloque toutes les opérations temporelles (extraire le mois, filtrer une plage, trier chronologiquement). Le type n’est pas un détail cosmétique : il détermine quelles opérations Pandas autorise sur la colonne.
# Convertir la colonne 'date' en datetime# errors='coerce' transformera les dates invalides en NaT (Not a Time)df['date'] = pd.to_datetime(df['date'], errors='coerce')print(f"Colonne date convertie en datetime : dtype = {df['date'].dtype}")
Colonne date convertie en datetime : dtype = datetime64[us]
Verification de la conversion
Verifions que la colonne date a bien ete convertie en type datetime et que les autres colonnes sont correctement typees. Cela nous permettra d’exploiter les fonctionnalites temporelles de Pandas (extraction de mois, annee, tri chronologique, etc.).
Une fois les données propres et correctement typées, on peut les enrichir : créer une colonne dérivée (chiffre_affaires = quantite × prix_unitaire) qui n’existait pas dans la source mais qui porte directement la réponse à la question métier. Cette étape de feature engineering est celle qui transforme des données brutes en information analysable — c’est aussi elle qu’un agent IA devra savoir reproduire pour produire des insights actionnables plutôt que de simples vues des données.
# Créer une colonne 'chiffre_affaires'df['chiffre_affaires'] = df['quantite'] * df['prix_unitaire']df.head()
date
id_produit
categorie
quantite
prix_unitaire
chiffre_affaires
0
2023-10-01
A101
Electronique
5.0
120.0
600.0
1
2023-10-01
B202
Livre
10.0
15.5
155.0
2
2023-10-02
A101
Electronique
3.0
120.0
360.0
3
2023-10-03
C303
Maison
2.0
75.9
151.8
4
2023-10-03
B202
Livre
6.0
15.5
93.0
Étape 5 : Agrégation pour l’Analyse
Point d’aboutissement du pipeline : les données étant propres, typées et enrichies, l’agrégation (groupby) permet enfin de répondre à une question métier — ici, le chiffre d’affaires par catégorie. C’est le moment où le travail ingrat des étapes 1 à 4 porte ses fruits : un groupby sur une colonne mal typée ou truffée de NaN aurait produit des résultats silencieusement faux. L’ordre inspection → nettoyage → typage → transformation → agrégation n’est pas arbitraire : chaque étape débloque la fiabilité de la suivante.
# Question métier : Quel est le chiffre d'affaires total par catégorie de produit ?ca_par_categorie = df.groupby('categorie')['chiffre_affaires'].sum().reset_index()print("Chiffre d'affaires total par catégorie :")print(ca_par_categorie)
Chiffre d'affaires total par catégorie :
categorie chiffre_affaires
0 Electronique 1440.0
1 Livre 248.0
2 Maison 151.8
Exercices
Exercice 1 : Analyse temporelle
A partir du DataFrame df (nettoyé), créez une analyse qui : 1. Extrait le mois de chaque transaction dans une nouvelle colonne mois 2. Calcule le chiffre d’affaires total par mois 3. Affiche le mois avec le chiffre d’affaires le plus élevé
Indices : Utilisez dt.month pour extraire le mois d’une datetime, puis groupby() et sum().
# Votre code pour l'Exercice 1#Exemple guide: Extrait le mois de chaque transactiondf['mois'] =None# TODO etudiant#Exemple guide: Calculez le chiffre d'affaires total par moisca_par_mois =None# TODO etudiant#Exemple guide: Trouvez le mois avec le CA le plus élevémois_max_ca =None# TODO etudiant# Affichage des résultatsprint("Chiffre d'affaires par mois :")print(ca_par_mois)print(f"\nMois avec le CA le plus élevé : {mois_max_ca}")
Chiffre d'affaires par mois :
None
Mois avec le CA le plus élevé : None
Exercice 2 : Detection d’anomalies (méthode IQR)
Les valeurs aberrantes (outliers) peuvent fausser vos analyses. Créez une fonction qui : 1. Calcule les bornes d’une colonne numérique en utilisant la méthode de l’écart interquartile (IQR) 2. Identifie les transactions dont le chiffre d’affaires est une anomalie (en dehors des bornes) 3. Affiche le nombre d’anomalies détectées et leurs détails
Indices : Utilisez quantile() pour obtenir Q1 et Q3, puis un filtre booléen pour identifier les anomalies.
Référence. La méthode des bornes à 1,5×IQR et le box-plot (boîte à moustaches) qui l’illustre ont été introduits par John W. Tukey dans Exploratory Data Analysis (Addison-Wesley, 1977), ouvrage fondateur de l’analyse exploratoire de données. Sous une distribution normale, ces bornes signalent environ 0,7% des observations comme potentiellement aberrantes.
# Votre code pour l'Exercice 2def detecter_anomalies_iqr(data, colonne):""" Détecte les anomalies dans une colonne en utilisant la méthode IQR. Args: data: DataFrame Pandas colonne: Nom de la colonne à analyser Returns: Tuple: (DataFrame des anomalies, borne inférieure, borne supérieure) """# Exercice: Calculer Q1 (25ème percentile) et Q3 (75ème percentile) Q1 =None Q3 =None# Exercice: Calculer l'écart interquartile (IQR) IQR =None# Exercice: Calculer les bornes inférieure et supérieure borne_inf =None borne_sup =None# Exercice: Filtrer les anomalies anomalies =Nonereturn anomalies, borne_inf, borne_sup# Appliquer la fonction au chiffre d'affairesanomalies_ca, inf, sup = detecter_anomalies_iqr(df, 'chiffre_affaires')if inf isnotNoneand sup isnotNone:print(f"Bornes IQR: [{inf:.2f}, {sup:.2f}]")print(f"\nNombre d'anomalies détectées: {len(anomalies_ca) if anomalies_ca isnotNoneelse0}")if anomalies_ca isnotNoneandlen(anomalies_ca) >0:print("\nDétail des anomalies:")print(anomalies_ca[['date', 'id_produit', 'chiffre_affaires']])else:print("Remplissez d'abord les TODO dans detecter_anomalies_iqr() pour voir les résultats.")
Remplissez d'abord les TODO dans detecter_anomalies_iqr() pour voir les résultats.
Exercice 3 : Detection et correction de doublons
Les doublons sont un problème frequent dans les jeux de données reels (erreurs de saisie, imports multiples). Vous allez ecrire une fonction qui detecte et gere les lignes dupliquees dans un DataFrame.
Objectif : Créer une fonction qui identifie les doublons partiels (même id_produit et même date) et propose une stratégie de deduplication (garder la ligne avec la valeur la plus eleveee, ou fusionner en moyennant).
Indices : - Utilisez df.duplicated(subset=['id_produit', 'date']) pour detecter les doublons partiels - Utilisez df.drop_duplicates() avec le paramètre subset pour les supprimer - Pour une fusion plus avancee, utilisez groupby() avec .agg() pour moyenner les valeurs numériques
# Exercice 3 : Detection et correction de doublons# Creez une fonction qui detecte et deduplique les transactionsdef detecter_et_dedupliquer(data, colonnes_cle):""" Detecte les doublons partiels et applique une strategie de deduplication. Args: data: DataFrame Pandas colonnes_cle: liste des colonnes definissant un doublon (ex: ['id_produit', 'date']) Returns: Tuple: (DataFrame deduplique, nombre de doublons detectes) """# Etape 1: Detectez les doublons partiels# Indice: data.duplicated(subset=colonnes_cle, keep=False) masque_doublons =None# Etape 2: Comptez le nombre de doublons nb_doublons =None# Etape 3: Appliquez la deduplication# Indice: groupby sur colonnes_cle + agg pour moyenner les valeurs numeriques# Ou plus simplement: data.drop_duplicates(subset=colonnes_cle, keep='last') df_deduplique =Nonereturn df_deduplique, nb_doublons# Testez la fonction sur le DataFrame df# Indice: appelez detecter_et_dedupliquer(df, ['id_produit', 'date'])# result_dedup, nb = detecter_et_dedupliquer(df, ['id_produit', 'date'])# print(f"Doublons detectes : {nb}")# print(f"Lignes avant : {len(df)}, apres : {len(result_dedup)}")print("Exercice 3 a completer : detection et correction de doublons")
Exercice 3 a completer : detection et correction de doublons
Conclusion
Félicitations ! Vous avez nettoyé un jeu de données, corrigé ses types, créé de nouvelles informations et répondu à une question métier grâce à une agrégation.
Vous avez appris à : - Identifier les problèmes avec .info() et .isnull(). - Gérer les valeurs manquantes avec dropna et fillna (de manière avancée avec groupby et transform). - Corriger les types de données avec pd.to_datetime. - Créer de nouvelles colonnes pour enrichir vos données. - Agréger les données avec groupby() pour obtenir des insights.
Lien avec l’après-midi : Ces étapes de nettoyage et d’analyse sont exactement le type de tâches qu’un agent d’IA pourra bientôt réaliser de manière autonome. En maîtrisant ces techniques, vous comprenez la logique qu’il faudra implémenter dans les “outils” que nous fournirons à nos agents pour qu’ils puissent travailler efficacement avec des données du monde réel.
References
CrowdFlower, Data Science Report, 2016 ; vulgarisé par G. Press, Cleaning Big Data: Most Time-Consuming, Least Enjoyable Data Science Task, Survey Says, Forbes, 23 mars 2016. Enquête établissant la règle des 80/20 : ~80% du temps des data scientists consacré à la préparation/nettoyage des données. Concept central de l’introduction de ce laboratoire.
J. W. Tukey, Exploratory Data Analysis, Addison-Wesley, Reading, MA, 1977. Ouvrage fondateur de l’analyse exploratoire de données ; introduit le box-plot et la règle des bornes à 1,5×IQR pour la détection de valeurs aberrantes (Exercice 2).
W. McKinney, Data Structures for Statistical Computing in Python, Proc. SciPy 2010, pp. 51-56. Sous-jacent aux manipulations DataFrame de ce laboratoire (pandas) — référence détaillée au Lab 1.3.