ITSkillsCenter
Blog

Installer Pandas et préparer l environnement

11 min de lecture

Ce que vous saurez faire à la fin

  1. Charger un fichier CSV, Excel ou JSON dans un DataFrame pandas et inspecter sa structure en 4 commandes essentielles.
  2. Nettoyer des données réelles bruitées : dates mal formatées, montants en FCFA collés au mot, valeurs manquantes, doublons silencieux.
  3. Filtrer, trier, regrouper et agréger des dizaines de milliers de lignes avec groupby, agg, pivot_table et merge.
  4. Créer des colonnes calculées, des segments RFM et des cohortes mensuelles pour piloter une PME sénégalaise comme une équipe data.
  5. Exporter des rapports prêts à diffuser au format Excel multi-onglets, CSV UTF-8 et graphiques PNG transmissibles par WhatsApp.

Durée : 4h. Pré-requis : Python 3.10+, JupyterLab ou VS Code, pandas 2.x (pip install pandas openpyxl matplotlib), un fichier ventes_2025.csv exporté de votre logiciel de caisse, base de Python (variables, fonctions). Coût : 0 FCFA, tout est open source.

Étape 1 — Installer pandas et préparer l’environnement

Travaillez dans un environnement virtuel pour éviter les conflits avec d’autres projets. Une seule ligne suffit, et vous garantissez la reproductibilité sur n’importe quelle machine.

python -m venv venv_pandas
source venv_pandas/bin/activate         # Linux/Mac
venv_pandas\Scripts\activate            # Windows

pip install pandas openpyxl matplotlib jupyterlab
jupyter lab

JupyterLab s’ouvre dans le navigateur. Créez un notebook analyse_ventes.ipynb et commencez. La cellule magique %matplotlib inline affiche les graphiques directement sous le code.

Étape 2 — Charger le CSV et inspecter

Première chose à faire avec n’importe quel fichier : connaître sa taille, ses colonnes, ses types et un aperçu. Quatre commandes suffisent.

import pandas as pd

df = pd.read_csv("ventes_2025.csv", sep=";", encoding="utf-8")

print(df.shape)            # (45218, 12) lignes, colonnes
print(df.head())           # 5 premières lignes
print(df.dtypes)           # type de chaque colonne
print(df.describe())       # stats numériques (count, mean, std, min, max)

Si le fichier vient d’Excel exporté par un caissier, le séparateur est souvent point-virgule (sep= »; ») et l’encodage cp1252 ou latin-1. En cas d’erreur UnicodeDecodeError, essayez encoding= »latin-1″.

Étape 3 — Renommer et nettoyer les noms de colonnes

Les exports métier ont souvent des colonnes mal nommées : « Montant total HT (FCFA) », « Date de vente », « Nom Client ». On uniformise tout en snake_case ASCII pour pouvoir taper df.montant sans guillemets.

df.columns = (
    df.columns
    .str.lower()
    .str.replace(r"[^a-z0-9]+", "_", regex=True)
    .str.strip("_")
)

print(df.columns.tolist())
# ['date_vente', 'client', 'produit', 'quantite', 'montant_fcfa', ...]

La regex remplace tout caractère non alphanumérique par un underscore, puis on retire les underscores en début et fin. Plus jamais de pd KeyError pour cause d’espace ou d’accent oublié.

Étape 4 — Convertir les types de données

Une date au format texte ne se trie pas correctement. Un montant en FCFA stocké comme string ne s’additionne pas. Convertissez tout au bon type dès le départ.

df["date_vente"]   = pd.to_datetime(df["date_vente"], format="%d/%m/%Y", errors="coerce")
df["montant_fcfa"] = (
    df["montant_fcfa"].astype(str)
       .str.replace(" ", "")
       .str.replace("FCFA", "")
       .str.replace(",", ".")
       .astype(float)
)
df["quantite"]     = pd.to_numeric(df["quantite"], errors="coerce").fillna(0).astype(int)

print(df.dtypes)

errors= »coerce » convertit les valeurs invalides en NaT (date) ou NaN (numérique) au lieu de planter. On les traite ensuite proprement à l’étape suivante.

Étape 5 — Détecter et traiter les valeurs manquantes

Un export propre n’existe pas. Il y a toujours des lignes vides, des champs oubliés. Première règle : compter, comprendre, puis décider (supprimer, remplir, signaler).

print(df.isna().sum())                 # nb de NaN par colonne
print(df.isna().sum() / len(df) * 100) # % de NaN par colonne

# Stratégie 1 : supprimer les lignes sans date (inexploitables)
df = df.dropna(subset=["date_vente"])

# Stratégie 2 : remplacer les quantites vides par 1
df["quantite"] = df["quantite"].fillna(1)

# Stratégie 3 : marquer "Inconnu" pour les clients non identifiés
df["client"] = df["client"].fillna("Client_inconnu")

Ne jamais utiliser df.dropna() seul sans subset : vous risquez de supprimer 80% du fichier si une seule colonne est souvent vide. Toujours préciser quelles colonnes sont critiques.

Étape 6 — Supprimer les doublons silencieux

Les doublons faussent toutes les agrégations. Une vente enregistrée 2 fois double le CA. Détection simple, suppression chirurgicale.

print("Lignes avant :", len(df))
print("Doublons     :", df.duplicated().sum())

# Doublons sur clé métier (même client, même date, même montant)
df = df.drop_duplicates(subset=["client", "date_vente", "montant_fcfa"])

print("Lignes apres :", len(df))

Ne pas utiliser drop_duplicates() sur toutes les colonnes : deux ventes identiques mais avec un id_transaction différent seraient gardées. Choisissez la clé métier qui définit « même vente ».

Étape 7 — Filtrer avec des conditions multiples

pandas accepte des masques booléens combinés avec & (et), | (ou), ~ (non). Indispensable pour isoler les ventes du Plateau au-dessus de 50 000 FCFA.

masque = (
      (df["boutique"] == "Plateau")
    & (df["montant_fcfa"] >= 50000)
    & (df["date_vente"]   >= "2025-11-01")
)

df_plateau_premium = df[masque]
print(df_plateau_premium.shape)
print(df_plateau_premium["montant_fcfa"].sum(), "FCFA")

Toujours mettre chaque condition entre parenthèses. Sans elles, l’opérateur & a une priorité différente et le résultat est silencieusement faux.

Étape 8 — Grouper et agréger avec groupby

groupby est le couteau suisse de pandas. Il regroupe les lignes selon une clé puis applique une agrégation : somme, moyenne, comptage, premier, dernier.

resume_boutique = (
    df.groupby("boutique")
      .agg(
          nb_ventes      = ("montant_fcfa", "count"),
          ca_total_fcfa  = ("montant_fcfa", "sum"),
          panier_moyen   = ("montant_fcfa", "mean"),
          ca_max         = ("montant_fcfa", "max"),
      )
      .sort_values("ca_total_fcfa", ascending=False)
      .round(0)
      .astype({"panier_moyen": int, "ca_max": int})
)

print(resume_boutique)

La syntaxe nommée (nb_ventes = (« montant_fcfa », « count »)) donne des noms de colonnes propres dès la sortie. Plus besoin de renommer après coup.

Étape 9 — Pivot table pour croiser deux dimensions

Le pivot_table reproduit l’équivalent du tableau croisé dynamique d’Excel mais en code, donc reproductible et automatisable.

pivot = pd.pivot_table(
    df,
    index   = "boutique",
    columns = "categorie_produit",
    values  = "montant_fcfa",
    aggfunc = "sum",
    fill_value = 0,
    margins = True,
    margins_name = "Total",
).astype(int)

print(pivot)

margins=True ajoute la ligne et la colonne de totaux. fill_value=0 remplace les NaN par 0 pour qu’aucune cellule ne soit vide. Lecture immédiate par n’importe quel directeur commercial.

Étape 10 — Joindre deux DataFrames avec merge

Vous avez ventes.csv et clients.csv séparés. merge fusionne sur une clé commune, exactement comme un JOIN SQL. Quatre types : inner, left, right, outer.

clients = pd.read_csv("clients.csv", sep=";")
clients.columns = clients.columns.str.lower().str.replace(" ", "_")

df_complet = df.merge(
    clients[["id_client", "ville", "segment_rfm"]],
    left_on  = "client_id",
    right_on = "id_client",
    how      = "left",
)

print(df_complet.shape)
print(df_complet[["client_id", "ville", "segment_rfm"]].head())

how= »left » garde toutes les ventes même si le client manque dans clients.csv (l’info supplémentaire sera NaN). how= »inner » ne garderait que les ventes des clients connus. Choix selon votre objectif.

Étape 11 — Créer une colonne calculée et un segment RFM

Une nouvelle colonne se crée par affectation. On peut aussi appliquer une fonction conditionnelle avec np.select ou pd.cut pour classer.

import numpy as np

df["mois_vente"] = df["date_vente"].dt.to_period("M").astype(str)

conditions = [
    df["montant_fcfa"] < 10000,
    df["montant_fcfa"] < 50000,
    df["montant_fcfa"] < 200000,
]
choix = ["S", "M", "L"]
df["taille_panier"] = np.select(conditions, choix, default="XL")

print(df[["mois_vente", "montant_fcfa", "taille_panier"]].head(10))
print(df["taille_panier"].value_counts())

np.select est plus rapide et plus lisible que des if/elif imbriqués dans une fonction apply. Pour 1 million de lignes, gain typique : x50 sur le temps d’exécution.

Étape 12 — Cohortes mensuelles d’acquisition client

Une cohorte regroupe les clients selon leur premier achat. On compte combien restent actifs chaque mois suivant. Indicateur clé pour mesurer la fidélisation.

df["mois_vente"] = df["date_vente"].dt.to_period("M")

premiers = df.groupby("client_id")["mois_vente"].min().rename("cohorte")
df = df.merge(premiers, on="client_id")

df["mois_relatif"] = (df["mois_vente"] - df["cohorte"]).apply(lambda x: x.n)

cohortes = (
    df.groupby(["cohorte", "mois_relatif"])["client_id"]
      .nunique()
      .unstack(fill_value=0)
)
print(cohortes.head(12))

Chaque ligne = mois d’acquisition. Chaque colonne = nombre de mois après l’acquisition. La diagonale décroît, et la vitesse de décroissance révèle la qualité de la rétention.

Étape 13 — Visualiser les top 10 produits avec matplotlib

Une bonne agrégation mérite un graphique. matplotlib est intégré à pandas via la méthode .plot(). Un seul appel et vous avez un PNG prêt pour WhatsApp.

import matplotlib.pyplot as plt

top10 = (
    df.groupby("produit")["montant_fcfa"]
      .sum()
      .sort_values(ascending=False)
      .head(10)
)

ax = top10.plot(kind="barh", figsize=(10, 6), color="#2E86AB")
ax.set_title("Top 10 produits par CA — 2025 (FCFA)")
ax.set_xlabel("Chiffre d'affaires (FCFA)")
ax.invert_yaxis()
plt.tight_layout()
plt.savefig("top10_produits.png", dpi=150)
plt.show()

kind= »barh » donne des barres horizontales, plus lisibles que verticales pour des noms de produits longs. dpi=150 garantit une qualité correcte sur écran et impression.

Étape 14 — Exporter un rapport Excel multi-onglets

Le directeur veut un fichier unique avec un onglet par boutique, un onglet récap, un onglet top produits. ExcelWriter le fait en 10 lignes.

with pd.ExcelWriter("rapport_2025.xlsx", engine="openpyxl") as writer:
    resume_boutique.to_excel(writer, sheet_name="Recap_Boutiques")
    pivot.to_excel(writer, sheet_name="Croise_Categories")
    top10.to_excel(writer, sheet_name="Top10_Produits")

    for boutique, sous_df in df.groupby("boutique"):
        nom_onglet = boutique[:31]   # Excel limite à 31 caracteres
        sous_df.to_excel(writer, sheet_name=nom_onglet, index=False)

print("Rapport genere : rapport_2025.xlsx")

engine= »openpyxl » est nécessaire (xlsxwriter est plus rapide mais ne gère pas les styles complexes). Le fichier généré pèse 1 à 5 Mo, transférable par WhatsApp Business sans compression.

Erreurs courantes à éviter

Lire un CSV sans préciser sep et encoding. pandas devine, mais devine mal sur les exports Excel français. Toujours vérifier les 5 premières lignes après chargement, et corriger sep ou encoding si les colonnes sont collées.

Utiliser .iterrows() pour boucler sur 100 000 lignes. 1000 fois plus lent qu’une opération vectorisée. Toujours chercher d’abord la version pandas (.apply, np.select, vectorisation pure) avant la boucle Python.

Modifier un slice sans .copy(). Le warning SettingWithCopyWarning n’est pas anodin : vos modifications peuvent ne pas être appliquées au DataFrame d’origine. Toujours df_filtre = df[masque].copy() si vous comptez modifier ensuite.

Confondre groupby().sum() et groupby().agg(). .sum() agrège toutes les colonnes numériques, parfois absurdement. Préférez .agg({« col »: « sum »}) qui est explicite et tolère les changements futurs de schéma.

Oublier que to_datetime sans format est lent. Sur 1 million de dates, parsing automatique = 30 secondes, parsing avec format= »%d/%m/%Y » = 1 seconde. Toujours préciser le format quand il est connu.

Exporter un CSV sans encoding= »utf-8-sig ». Excel ouvre alors les accents en charabia. Le suffixe -sig ajoute le BOM qui dit à Excel « c’est de l’UTF-8 ».

Pousser un notebook avec des données clients en clair sur GitHub. Toujours mettre *.csv et *.xlsx dans .gitignore, et fournir un sample anonymisé pour la reproductibilité.

Checklist finale avant livraison du rapport

  1. Le CSV source est chargé avec sep, encoding et dtype explicites, et les 5 premières lignes sont vérifiées visuellement.
  2. Toutes les colonnes ont été renommées en snake_case ASCII, sans accent ni espace.
  3. Les dates sont au type datetime64, les montants au type float64, les quantités au type int64.
  4. Le pourcentage de NaN par colonne est documenté, et chaque colonne critique a une stratégie (drop, fillna, marquage).
  5. Les doublons ont été détectés sur la clé métier et supprimés (ou conservés intentionnellement avec justification écrite).
  6. Les filtres complexes ont chaque condition entre parenthèses, et le nombre de lignes restantes est imprimé pour validation.
  7. Les groupby utilisent la syntaxe nommée agg(nom_colonne=(« source », « fonction »)) pour des noms propres.
  8. Les jointures merge précisent how= explicitement (jamais le défaut implicite) et la taille avant/après est vérifiée.
  9. Au moins un graphique matplotlib est exporté en PNG 150 dpi, prêt à insérer dans une présentation ou WhatsApp.
  10. Le rapport Excel multi-onglets est généré, ouvert dans Excel pour validation visuelle, et l’anti-virus ne le bloque pas.
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité