logo oujood
🔍

Projet Pandas : analyse de ventes

Ce projet applique toutes les compétences du cours sur un cas concret : analyser les données de ventes d'une boutique fictive. Du chargement des données jusqu'aux graphiques de synthèse, en passant par le nettoyage et les agrégations.

OUJOOD.COM

Présentation du projet

Ce projet analyse les données de ventes d'une boutique fictive sur six mois. L'objectif est de répondre à trois questions concrètes :

  • Quel mois a généré le plus de chiffre d'affaires ?
  • Quels sont les produits les plus vendus ?
  • Quel vendeur a la meilleure performance ?

Nous allons construire les données directement dans le script pour que l'exemple soit reproductible, mais la même logique s'applique à n'importe quel fichier CSV ou Excel réel.

Étape 1 — Créer et inspecter les données

  📋 Copier le code

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
n = 200

produits  = ["Clavier", "Souris", "Écran", "Casque", "Webcam"]
vendeurs  = ["Alice", "Bob", "Clara", "David"]
mois_list = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin"]
prix_ref  = {"Clavier": 45.90, "Souris": 22.50, "Écran": 189.00,
             "Casque": 79.99, "Webcam": 54.90}

produits_col = np.random.choice(produits, n)
vendeurs_col = np.random.choice(vendeurs, n)
mois_col     = np.random.choice(mois_list, n)
qte_col      = np.random.randint(1, 6, n)
prix_col     = [prix_ref[p] * np.random.uniform(0.95, 1.05) for p in produits_col]

df = pd.DataFrame({
    "mois":     mois_col,
    "vendeur":  vendeurs_col,
    "produit":  produits_col,
    "quantité": qte_col,
    "prix_unit": np.round(prix_col, 2)
})

# Introduire quelques valeurs manquantes volontairement
idx_nan = np.random.choice(df.index, 10, replace=False)
df.loc[idx_nan, "quantité"] = np.nan

# Inspection initiale
print("Dimensions :", df.shape)
print(df.head())
print(df.isnull().sum())

Étape 2 — Nettoyage des données

  📋 Copier le code

import pandas as pd
import numpy as np

# (suite du script — df déjà créé ci-dessus)

# Remplir les quantités manquantes par la médiane
mediane_qte = df["quantité"].median()
df["quantité"] = df["quantité"].fillna(mediane_qte)
df["quantité"] = df["quantité"].astype(int)

# Calculer le montant total par ligne
df["montant"] = (df["quantité"] * df["prix_unit"]).round(2)

# Convertir mois en catégorie ordonnée pour le tri chronologique
ordre_mois = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin"]
df["mois"] = pd.Categorical(df["mois"], categories=ordre_mois, ordered=True)

print("Données nettoyées :")
print(df.dtypes)
print(df.describe().round(2))

Convertir la colonne mois en Categorical ordonné garantit que les graphiques et les tris respectent l'ordre chronologique, et non l'ordre alphabétique qui placerait Avril avant Janvier.

Étape 3 — Agrégations et réponses aux questions

  📋 Copier le code

import pandas as pd
import numpy as np

# (suite du script)

# Question 1 : CA par mois
ca_mois = df.groupby("mois", observed=True)["montant"].sum().reset_index()
ca_mois.columns = ["mois", "CA"]
print("CA par mois :")
print(ca_mois.sort_values("CA", ascending=False))

# Question 2 : produits les plus vendus (en quantité)
top_produits = (
    df.groupby("produit")["quantité"]
      .sum()
      .sort_values(ascending=False)
      .reset_index()
)
top_produits.columns = ["produit", "total_vendu"]
print("\nTop produits :")
print(top_produits)

# Question 3 : performance par vendeur
perf_vendeurs = df.groupby("vendeur").agg(
    CA_total       = ("montant",  "sum"),
    nb_ventes      = ("montant",  "count"),
    panier_moyen   = ("montant",  "mean"),
    qte_totale     = ("quantité", "sum")
).round(2).reset_index()
print("\nPerformance par vendeur :")
print(perf_vendeurs.sort_values("CA_total", ascending=False))

Étape 4 — Visualisations de synthèse

  📋 Copier le code

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# (suite du script — ca_mois, top_produits, perf_vendeurs déjà calculés)

fig, axes = plt.subplots(1, 3, figsize=(16, 5))

# Graphique 1 : CA mensuel
axes[0].bar(ca_mois["mois"], ca_mois["CA"], color="steelblue")
axes[0].set_title("Chiffre d'affaires mensuel")
axes[0].set_xlabel("Mois")
axes[0].set_ylabel("CA (€)")
axes[0].tick_params(axis="x", rotation=30)

# Graphique 2 : Top produits
axes[1].barh(top_produits["produit"], top_produits["total_vendu"], color="coral")
axes[1].set_title("Produits les plus vendus")
axes[1].set_xlabel("Quantité totale")

# Graphique 3 : CA par vendeur
axes[2].bar(perf_vendeurs["vendeur"], perf_vendeurs["CA_total"], color="seagreen")
axes[2].set_title("CA par vendeur")
axes[2].set_xlabel("Vendeur")
axes[2].set_ylabel("CA (€)")

plt.suptitle("Tableau de bord — Analyse des ventes S1", fontsize=14, fontweight="bold")
plt.tight_layout()
plt.show()

La fonction plt.subplots(1, 3) crée une grille de trois graphiques côte à côte dans une seule figure. axes[0], axes[1] et axes[2] désignent chaque graphique. plt.suptitle() ajoute un titre général au-dessus de la grille. C'est la structure de base d'un tableau de bord analytique.

Ce projet a mobilisé dans l'ordre : création de données, inspection, nettoyage avec fillna() et astype(), catégorie ordonnée, agrégations avec groupby() et agg(), et visualisation multi-panneaux. C'est un pipeline complet représentatif de ce que vous ferez sur des données réelles.

Par carabde | Mis à jour le 26 avril 2026