Premier contact avec un jeu de données

Première leçon du cours Analyse exploratoire des données, en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Dresser le profil d'un DataFrame (dimensions, types, aperçu, résumé statistique)
  • Corriger les types de colonnes mal importées (nombres, dates)
  • Formuler des questions d'analyse avant de calculer

Profilage des donnéesTypes pandas

L’analyse exploratoire des données (EDA, exploratory data analysis) consiste à comprendre un jeu de données avant de le modéliser ou d’en tirer des conclusions : sa structure, sa qualité, ses distributions et ses relations. C’est l’étape où l’on découvre les pièges… et les premières pistes.

Commencer par les questions et le grain

Avant de coder, deux questions :

  1. Que veut-on savoir ? « Quelles régions et catégories portent le chiffre d’affaires ? Y a-t-il une saisonnalité ? »
  2. Que représente une ligne ? Une commande, une ligne de commande, un client, un jour ? Ce grain conditionne tous les calculs : sommer des montants de lignes de commande n’a pas le même sens que compter des commandes.

La revue de base

import pandas as pd

ventes = pd.DataFrame({
    "commande_id": [101, 102, 103, 104],
    "date": ["2026-01-03", "2026-01-04", "2026-01-04", "2026-01-10"],
    "region": ["Nord", "Sud", "Nord", "Est"],
    "quantite": [2, 1, 3, 1],
    "montant": ["39,90", "12,50", "59,85", "24,00"],   # virgule décimale : lu comme texte
})

print(ventes.shape)        # (4, 5) : 4 lignes, 5 colonnes
print(ventes.head())       # aperçu des premières lignes
print(ventes.dtypes)       # type de chaque colonne
ventes.info()              # types, valeurs non nulles, mémoire
print(ventes.describe())   # statistiques des colonnes numériques
print(ventes.nunique())    # nombre de valeurs distinctes par colonne

Lecture attentive des résultats :

  • montant est de type str : la virgule décimale l’a empêché d’être lu comme un nombre. Depuis pandas 3, le texte a par défaut le type str (auparavant object).
  • date est aussi du texte : impossible de trier ou grouper par mois correctement.
  • commande_id est numérique, mais c’est un identifiant : sa moyenne dans describe() n’a aucun sens. Vérifier nunique() == nombre de lignes confirme qu’il identifie bien chaque ligne.

Corriger les types

ventes["montant"] = pd.to_numeric(ventes["montant"].str.replace(",", ".", regex=False))
ventes["date"] = pd.to_datetime(ventes["date"], errors="coerce")
print(ventes.dtypes)   # montant float64, date datetime64

errors="coerce" transforme les valeurs impossibles à convertir en valeurs manquantes (NaT pour les dates) au lieu de lever une erreur. Contrôle toujours combien de valeurs ont été perdues :

print(ventes["date"].isna().sum())

Sélectionner par type

numeriques = ventes.select_dtypes(include="number").columns.tolist()
autres = ventes.select_dtypes(exclude="number").columns.tolist()
print(ventes.describe(include="all"))   # résumé de toutes les colonnes

Noter ses observations

Garde une liste au fil de l’eau : « montant importé en texte », « 3 régions seulement », « période de janvier à mars ». Ce journal deviendra la base de ta synthèse finale.

À retenir

  • Questions métier et grain d’abord.
  • shape, dtypes, info, describe, nunique : le profil de départ.
  • Corrige les types, puis vérifie les valeurs perdues à la conversion.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 2Python dans le navigateur2 indices

    Fonction de profil

    Écris profil(df) qui renvoie un dictionnaire avec les clés n_lignes, n_colonnes, numeriques (liste des colonnes numériques) et cle_unique (True si la colonne commande_id a autant de valeurs distinctes que de lignes).

    import pandas as pd
    
    ventes = pd.DataFrame({
        'commande_id': [101, 102, 103, 104, 105, 106, 107, 108],
        'date': ['2026-01-03', '2026-01-04', '2026-01-04', '2026-01-10', '2026-02-02', '2026-02-03', '2026-02-15', '2026-03-01'],
        'region': ['Nord', 'Sud', 'Nord', 'Est', 'Sud', 'Nord', 'Est', 'Sud'],
        'categorie': ['jeux', 'livres', 'jeux', 'deco', 'livres', 'deco', 'jeux', 'livres'],
        'quantite': [2, 1, 3, 1, 2, 4, 1, 2],
        'montant': ['39,90', '12,50', '59,85', '24,00', '25,00', '96,00', '19,95', '25,00'],
    })
    
    def profil(df):
        pass
  2. CodeDifficulté 2Python dans le navigateur2 indices

    Corriger les types

    Convertis montant en nombre (remplace la virgule par un point) et date en datetime avec errors='coerce'. Stocke ensuite dans nb_dates_invalides le nombre de dates non converties et dans ca_total la somme des montants.

    import pandas as pd
    
    ventes = pd.DataFrame({
        'date': ['2026-01-03', '2026-01-04', '2026-02-30', '2026-03-01'],
        'montant': ['39,90', '12,50', '59,85', '24,00'],
    })
    
    # conversions puis nb_dates_invalides et ca_total
  3. QCMDifficulté 11 indice

    Le grain des données

    Un fichier contient une ligne par produit commandé : la commande 12 apparaît 3 fois (3 produits). Pour compter le nombre de commandes, que faut-il utiliser ?

    • len(df)
    • df['commande_id'].nunique()
    • df['commande_id'].sum()
    • df.shape[1]

Quiz de fin de leçon

  1. Depuis pandas 3, quel est le type par défaut d’une colonne de texte ?

    • object
    • str
    • category
  2. Que fait pd.to_datetime(s, errors=‘coerce’) face à une date invalide ?

    • Il lève une erreur
    • Il la remplace par NaT
    • Il la supprime de la série
  3. Par défaut, describe() résume :

    • Toutes les colonnes
    • Les colonnes numériques
    • Les colonnes de texte

La suite du cours

  1. Valeurs manquantes et doublons18 min
  2. Analyse univariée : distributions et catégories18 min
  3. Analyse bivariée : croiser les variables20 min
  4. Anomalies, évolution temporelle et synthèse de l'EDA20 min

Analyse exploratoire des données · Intermédiaire · 3 h 01