← Retour au portfolio RSS

· 3 min de lecture

pandas : des données brutes au tableau propre

Étape 2 : lire, nettoyer, transformer et agréger des données réelles, là où se joue la qualité d'un modèle.

Dans un vrai projet, on passe bien plus de temps à préparer les données qu’à entraîner le modèle. pandas est l’outil de cette préparation : lire, nettoyer, transformer, agréger. Un modèle entraîné sur des données sales donne des résultats faux, avec beaucoup d’assurance.

Series et DataFrame

Une Series est une colonne étiquetée, un DataFrame un tableau de colonnes qui partagent le même index. Chaque colonne est un tableau NumPy : tout ce qui a été vu à l’étape précédente s’applique.

import pandas as pd

df = pd.read_csv("ventes.csv", parse_dates=["date"])
df.shape          # (lignes, colonnes)
df.head()         # les 5 premières lignes
df.info()         # types et valeurs manquantes, colonne par colonne
df.describe()     # statistiques des colonnes numériques

info() et describe() sont les deux premières commandes à lancer sur n’importe quel jeu de données. Elles révèlent la moitié des problèmes.

Sélectionner et filtrer

df["montant"]                             # une colonne (Series)
df[["client", "montant"]]                 # plusieurs colonnes (DataFrame)
df.loc[df["montant"] > 100, "client"]     # filtre + colonne, par étiquettes
df.iloc[:10, :3]                          # par positions

grosses_ventes = df.query("montant > 100 and pays == 'BF'")

loc travaille avec des étiquettes, iloc avec des positions. Les confondre est une source classique de bugs silencieux.

Nettoyer

df.isna().sum()                               # valeurs manquantes par colonne
df = df.drop_duplicates()
df["montant"] = df["montant"].fillna(df["montant"].median())
df["pays"] = df["pays"].str.strip().str.upper()
df = df[df["montant"] >= 0]                    # valeurs aberrantes

Pour les valeurs manquantes, pas de règle universelle : supprimer la ligne, remplir par la médiane, ou créer une colonne « était manquant ». Le bon choix dépend du pourquoi de l’absence, et c’est une vraie décision, pas un détail technique.

Transformer : créer des variables

C’est ici que la connaissance du métier fait la différence entre un modèle moyen et un bon modèle.

df["mois"] = df["date"].dt.month
df["jour_semaine"] = df["date"].dt.day_name()
df["panier_moyen"] = df["montant"] / df["nb_articles"]
df["gros_client"] = df["montant"] > df["montant"].quantile(0.9)

Agréger : groupby

par_pays = (
    df.groupby("pays")
      .agg(ca=("montant", "sum"), ventes=("montant", "size"), moyen=("montant", "mean"))
      .sort_values("ca", ascending=False)
)

Le trio split / apply / combine répond à la majorité des questions métier : quel pays, quel mois, quel client ?

Joindre des tables

clients = pd.read_csv("clients.csv")
df = df.merge(clients, on="client_id", how="left")

Après chaque merge, vérifiez que le nombre de lignes n’a pas explosé : une clé dupliquée d’un côté multiplie les lignes de l’autre.

Visualiser pour comprendre

import matplotlib.pyplot as plt

df["montant"].hist(bins=50)
df.groupby("mois")["montant"].sum().plot(kind="bar")
plt.show()

Un histogramme montre en une seconde une distribution très asymétrique ou des valeurs impossibles, qu’aucune moyenne ne révèle.

Projet pour valider l’étape

Prendre le jeu de données Titanic sur Kaggle et produire un notebook propre qui :

  1. décrit chaque colonne et ses valeurs manquantes ;
  2. justifie une stratégie de remplissage pour l’âge ;
  3. crée au moins trois nouvelles variables (taille de la famille, titre extrait du nom…) ;
  4. répond par des groupby à : qui a survécu, selon la classe, le sexe, l’âge ?

Ce notebook sera réutilisé tel quel à l’étape suivante, pour entraîner le premier modèle.

Ressources