Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

🐼 Pandas – L'Analyse de Données en Python

Guide complet IDEO-Lab : DataFrame, Series, I/O, GroupBy, Merge & Preprocessing.

1.1 Facile

Vue d'ensemble

Data Analysis & Manipulation. (Excel/SQL en Python).

Data Science Python
1.2 Facile

Pourquoi Pandas ?

Le DataFrame. Input pour Scikit-learn, TF, PyTorch.

DataFrame ETL
1.3 Facile

Installation

pip install pandas. Dépend de NumPy. import pandas as pd.

pip import pandas as pd
1.4 Facile

Concept N°1 : Series (1D)

Une colonne de DataFrame. (Array NumPy + Index).

Series 1D
2.1 Facile

Concept N°2 : DataFrame (2D)

Tableau (type Excel). Collection de Series (Colonnes).

DataFrame 2D
2.2 Facile

I/O (Lecture & Écriture)

pd.read_csv, pd.read_excel, pd.read_sql. df.to_csv.

read_csv to_csv
2.3 Facile

Inspection (Analyse)

.head(), .info(), .describe(), .shape, .columns.

.head() .info()
2.4 Moyen

Sélection N°1 : .loc[] (Label)

Sélection par **Nom** (label) de l'index et des colonnes.

.loc Label-based
3.1 Moyen

Sélection N°2 : .iloc[] (Index)

Sélection par **Position** (entier) [0, 1, 2...].

.iloc Integer-based
3.2 Moyen

Sélection N°3 : Masque Booléen

df[df['age'] > 30]. (Filtrage conditionnel).

Boolean Mask Filtre
3.3 Facile

Nettoyage : Données Manquantes

.isnull().sum(), .dropna(), .fillna().

.dropna() .fillna()
3.4 Facile

Nettoyage : Types & Doublons

.astype() (ex: 'category'), .drop_duplicates().

.astype() .drop_duplicates()
4.1 Facile

Manipulation (Colonnes)

Ajouter (df['new']), Supprimer (.drop(axis=1)).

.drop() axis=1
4.2 Moyen

Manipulation (.apply)

Appliquer une fonction (ou lambda) à une colonne/ligne.

.apply() lambda
4.3 Avancé

📊 Agrégation : .groupby()

Split-Apply-Combine. (.agg(), .mean(), .sum()).

.groupby() Split-Apply-Combine
4.4 Avancé

Combinaison : merge()

Jointures (SQL JOINs : inner, left, right, outer).

merge JOIN
5.1 Moyen

Combinaison : concat()

"Empiler" des DataFrames (lignes: axis=0) (SQL UNION).

concat axis=0
5.2 Facile

Vitrine (Qui l'utilise ?)

Standard de la Data Science (Spotify, Airbnb, Finance, R&D).

Data Science Standard
5.3 Facile

Liens Utiles & Formation

pandas.pydata.org (User Guide), Cheat Sheets.

Documentation User Guide
5.4 Facile

Cheat-sheet

Workflow (Read, Inspect, Select, Clean, GroupBy).

cheat Workflow
1.1 Vue d'ensemble : L'Excel du Pythoniste
Qu'est-ce que Pandas ?

Pandas (Panel Data) est la **bibliothèque (library)** open-source N°1 en Python pour la **manipulation et l'analyse de données (Data Analysis)**.

Elle fournit des structures de données (DataFrame) et des fonctions (groupby, merge) performantes et faciles à utiliser, qui remplacent efficacement Excel ou SQL pour de nombreuses tâches.

Elle est construite sur **NumPy** et constitue la base de l'écosystème "PyData" (SciPy, Scikit-learn, Matplotlib...).

Diagramme : L'Écosystème PyData
+-------------------------+
| Matplotlib / Seaborn    | (Visualisation)
+-------------------------+
      ^
      | (Input)
+-------------------------+
| Scikit-learn / TF / PyTorch | (Machine Learning)
+-------------------------+
      ^
      | (Input: .values)
+-------------------------+
| Pandas (DataFrame)      | (Manipulation)
+-------------------------+
      ^
      | (Base)
+-------------------------+
| NumPy (ndarray)         | (Calcul Numérique)
+-------------------------+
1.2 Pourquoi Pandas ? (Le DataFrame)

Pandas résout le problème des données "tabulaires" (structurées) en Python.

OutilProblèmeSolution Pandas
Python (Listes/Dicts)Lent. Pas d'opérations vectorisées. Complexe pour les agrégats.Performances (via NumPy). API simple (.mean()).
ExcelNe scale pas (limite de lignes). Non-reproductible (clics).Gère des millions de lignes. Reproductible (scripts).
SQLOrienté "Set" (ensembles). Complexe pour l'analyse statistique ou ML.Orienté "DataFrame". Intégration totale avec Python (ML).

Pandas est le **"prétraitement" (ETL)** de 90% des workflows de Machine Learning (Scikit-learn, TF, PyTorch).

1.3 Installation & Import

L'installation se fait via pip ou conda. (Un environnement virtuel Python venv est fortement recommandé).

# 1. Installation (via pip)
# (Installe aussi NumPy)
pip install pandas

# (Pour Excel:
# pip install openpyxl
# (Pour SQL:
# pip install sqlalchemy
Import (Convention)

L'alias pd est la convention universelle (tout comme np pour NumPy).

import pandas as pd
import numpy as np

print(pd.__version__)
1.4 Concept N°1 : Series (1D)

Une Series est un tableau 1D (similaire à NumPy) mais avec un **Index** (labels).

C'est la structure qui représente **une colonne** d'un DataFrame.

# Création (Index par défaut [0, 1, 2])
s = pd.Series([10, 20, 30])
# 0    10
# 1    20
# 2    30
# dtype: int64

# Création (Index custom)
s_custom = pd.Series(
    [10, 20, 30],
    index=['a', 'b', 'c']
)
# a    10
# b    20
# c    30
# dtype: int64

# Accès (via l'index)
print(s_custom['b']) # 20
2.1 Concept N°2 : DataFrame (2D)

Le DataFrame (df) est l'objet principal de Pandas. C'est une structure 2D (Lignes et Colonnes) similaire à une feuille Excel ou une table SQL.

Un DataFrame est une **collection de Series** (les colonnes) qui partagent le même Index (les lignes).

Création (ex: depuis un Dictionnaire)
data = {
    'nom': ['Alice', 'Bob', 'Charlie'],
    'age': [25, 30, 35],
    'ville': ['Paris', 'Londres', 'Tokyo']
}

df = pd.DataFrame(data)

# (Affiche :)
#        nom  age    ville
# 0    Alice   25    Paris
# 1      Bob   30  Londres
# 2  Charlie   35    Tokyo

# (Les colonnes)
print(df.columns) # ['nom', 'age', 'ville']

# (L'index)
print(df.index) # RangeIndex(start=0, stop=3, step=1)
2.2 I/O (Lecture & Écriture)
CSV (Comma-Separated Values)

Le format le plus courant pour l'import/export de données tabulaires.

# 1. Lecture (CSV -> DataFrame)
df = pd.read_csv("mon_fichier.csv")

# (Options courantes)
df = pd.read_csv(
    "mon_fichier_custom.csv",
    sep=';',           // (Si le séparateur est ';')
    header=0,          // (Ligne 0 = en-têtes)
    usecols=['col1', 'col3'], // (Ne lire que ces colonnes)
    parse_dates=['date_col']  // (Convertir la colonne date)
)

# 2. Écriture (DataFrame -> CSV)
df.to_csv(
    "output.csv",
    index=False // (Ne pas inclure l'index Pandas [0, 1, 2...])
)
Autres Formats (Excel, SQL, JSON...)
# 1. Excel (Nécessite 'openpyxl')
df_excel = pd.read_excel(
    "mon_fichier.xlsx", 
    sheet_name="Feuil1"
)
df_excel.to_excel("output.xlsx", index=False)

# 2. SQL (Nécessite 'sqlalchemy')
from sqlalchemy import create_engine
engine = create_engine('sqlite:///ma_db.db')

df_sql = pd.read_sql("SELECT * FROM users", engine)
df_sql.to_sql("users_backup", engine, if_exists='replace')

# 3. JSON
df_json = pd.read_json("data.json")
df_json.to_json("output.json", orient='records')
2.3 Inspection (Comprendre les données)

Une fois le df chargé, la première étape est de l'inspecter.

Méthode / AttributDescription
.head(n=5)Affiche les 5 premières lignes. (.tail(5) pour les dernières).
.info()Le plus utile. Résumé des colonnes, types (Dtype), et nb de valeurs non-nulles.
.describe()Statistiques descriptives (moyenne, std, min, max, quartiles) pour les colonnes numériques.
.shape (Attribut)Retourne un tuple (nb_lignes, nb_colonnes).
.columns (Attribut)Liste des noms de colonnes.
.value_counts()(Sur une Series/Colonne) Compte les occurrences uniques (ex: df['ville'].value_counts()).
2.4 Sélection N°1 : .loc[] (Par Label/Nom)

.loc sélectionne les données par LABEL (le nom de l'index ou le nom de la colonne).

Syntaxe : df.loc[,]

# (Supposons un df avec index 'a', 'b', 'c'
# et colonnes 'age', 'ville')

# 1. Sélectionner une colonne (Series)
# (Ceci est le raccourci le plus courant)
col_age = df['age']
# (Équivalent à df.loc[:, 'age'])

# 2. Sélectionner plusieurs colonnes (DataFrame)
df_subset = df[['age', 'ville']]
# (Équivalent à df.loc[:, ['age', 'ville']])

# 3. Sélectionner une ligne (par label d'index)
ligne_b = df.loc['b'] # (Retourne une Series)

# 4. Sélectionner plusieurs lignes
lignes_ac = df.loc[['a', 'c']]

# 5. Sélection Ligne ET Colonne
cellule = df.loc['b', 'age'] // (Valeur unique)
subset = df.loc[['a', 'c'], ['age', 'ville']]
3.1 Sélection N°2 : .iloc[] (Par Position)

.iloc sélectionne les données par POSITION ENTIÈRE (0, 1, 2... style Python).

Syntaxe : df.iloc[,]

# 1. Sélectionner la 1ère ligne
ligne_0 = df.iloc[0]

# 2. Sélectionner la 1ère colonne
col_0 = df.iloc[:, 0]

# 3. Sélectionner les 5 premières lignes
lignes_0_4 = df.iloc[0:5] // (Slice Python, 5 est exclusif)

# 4. Sélectionner la dernière ligne
ligne_last = df.iloc[-1]

# 5. Sélection Ligne ET Colonne
cellule = df.iloc[0, 0] // (1ère ligne, 1ère colonne)
subset = df.iloc[0:5, [0, 2]] // (5 1ères lignes, cols 0 et 2)
3.2 Sélection N°3 : Masque Booléen (Filtre)

C'est la méthode de filtrage la plus puissante. On passe une Series de Booléens (le "masque") au df[].

1. Condition Simple
// 1. Créer le masque (une Series de True/False)
masque = df['age'] > 30

// 2. Appliquer le masque au DataFrame
df_filtre = df[masque]
// (Retourne que les lignes où le masque est True)
2. Conditions Multiples (&, |)

(Utiliser & (ET) et | (OU). Ne pas utiliser and/or. Parenthèses obligatoires).

masque_multi = (df['age'] > 30) & (df['ville'] == 'Paris')

df_filtre_multi = df[masque_multi]
3.3 Nettoyage : Données Manquantes (NaN)

Les données manquantes (NaN - Not a Number) sont le fléau de la Data Science. sklearn les rejette.

1. Détection
// (Compte les NaN par colonne)
print(df.isnull().sum())
// nom      0
// age      12 (12 NaN dans 'age')
// ville    2
2. Suppression (.dropna())
// (Supprime TOUTES les lignes
// ayant AU MOINS un NaN)
df_clean = df.dropna()

// (Supprime les colonnes ayant des NaN)
df_clean_cols = df.dropna(axis=1)
3. Remplacement (.fillna()) (Souvent préféré)
// (Remplacer les NaN 'age' par la moyenne)
mean_age = df['age'].mean()
df['age'] = df['age'].fillna(mean_age)

// (Remplacer les NaN 'ville' par "Inconnu")
df['ville'] = df['ville'].fillna("Inconnu")
3.4 Nettoyage : Types (.astype) & Doublons
Doublons (.drop_duplicates())
// 1. Vérifier les doublons
print(df.duplicated().sum())

// 2. Supprimer les lignes doublons
// (Garde la 1ère occurrence)
df_unique = df.drop_duplicates()

// 3. (Supprimer si 'email' est doublon)
df_unique_email = df.drop_duplicates(
    subset=['email']
)
Types (.astype())

.info() montre les types (Dtypes). object = string (gourmand en mémoire).

// 1. (Convertir un 'object' en 'datetime')
df['date_col'] = pd.to_datetime(df['date_col'])

// 2. (Convertir un 'float64' en 'int32')
df['age'] = df['age'].astype('int32')

// 3. (OPTIMISATION MEMOIRE)
// (Si 'ville' a peu de valeurs uniques)
df['ville'] = df['ville'].astype('category')
4.1 Manipulation (Ajouter/Supprimer Colonnes)
Ajouter une Colonne
// 1. Valeur statique
df['source'] = "Web"

// 2. Depuis une autre colonne
df['age_plus_un'] = df['age'] + 1

// 3. (Voir .apply() pour le complexe)
Supprimer (.drop())

axis=1 (Colonnes) ou axis=0 (Lignes).

// 1. Supprimer une colonne
// (inplace=True modifie df, sinon retourne une copie)
df.drop('col_inutile', axis=1, inplace=True)

// 2. Supprimer plusieurs colonnes
df.drop(
    ['col1', 'col2'], 
    axis=1, 
    inplace=True
)

// 3. Supprimer une ligne (par label d'index)
df.drop('index_a', axis=0, inplace=True)
4.2 Manipulation (.apply() & Lambda)

.apply() est le "couteau-suisse" pour appliquer une fonction complexe à chaque élément d'une Series (colonne) ou à chaque ligne (axis=1).

1. .apply() sur une Colonne (Series)
// (Fonction Python)
def classer_age(age):
    if age < 30:
        return "Jeune"
    else:
        return "Senior"

// (Appliquer la fonction à chaque 'age')
df['categorie_age'] = df['age'].apply(classer_age)

// (Version 'lambda' (anonyme), identique)
df['categorie_age'] = df['age'].apply(
    lambda x: "Jeune" if x < 30 else "Senior"
)
2. .apply() sur des Lignes (axis=1)

(Plus lent, mais utile si la logique dépend de plusieurs colonnes).

// (La lambda reçoit la 'ligne' (row) entière)
df['ratio'] = df.apply(
    lambda row: row['col_A'] / row['col_B'],
    axis=1 // (Spécifie "par ligne")
)
4.3 📊 Agrégation : .groupby() (Split-Apply-Combine)

C'est la fonctionnalité la plus puissante de Pandas (similaire au GROUP BY de SQL). Elle suit un processus en 3 étapes : **Split-Apply-Combine**.

Diagramme : Split-Apply-Combine
(DF Original)
+-------+-----+
| Ville | Prix|
+-------+-----+
| Paris | 100 |
| Tokyo | 150 |
| Paris | 200 |
| Tokyo | 250 |
+-------+-----+
      |
      | 1. SPLIT (par 'Ville')
      ▼
+-------+-----+     +-------+-----+
| Paris | 100 |     | Tokyo | 150 |
| Paris | 200 |     | Tokyo | 250 |
+-------+-----+     +-------+-----+
      |                   |
      | 2. APPLY (.mean())|
      ▼                   ▼
    [ 150 ]             [ 200 ]
      |                   |
      | 3. COMBINE        |
      ▼                   ▼
+-------+-----+
| Ville | Prix|
+-------+-----+
| Paris | 150 |
| Tokyo | 200 |
+-------+-----+
Syntaxe (.agg())
// 1. Grouper (ne calcule rien, crée un objet GroupBy)
grouped = df.groupby('ville')

// 2. Apply/Combine (calcul)
// (Moyenne des colonnes numériques)
moyennes = grouped.mean()

// (Syntaxe complète avec .agg() pour multi-calculs)
stats = df.groupby('ville').agg(
    salaire_moyen=('salaire', 'mean'),
    age_max=('age', 'max'),
    nb_clients=('nom', 'count')
)
4.4 Combinaison : pd.merge() (SQL JOIN)

pd.merge() est la fonction (similaire au JOIN SQL) pour combiner des DataFrames sur une (ou plusieurs) colonne(s) "clé".

INNER (Défaut)

Ne garde que les lignes où la clé existe dans les **deux** DataFrames.

df_clients = pd.DataFrame({
    'user_id': [1, 2, 3], 'nom': ['A', 'B', 'C']
})
df_achats = pd.DataFrame({
    'user_id': [2, 3, 4], 'achat': ['Pomme', 'Poire', 'Fraise']
})

// (Jointure sur 'user_id', how='inner')
df_inner = pd.merge(
    df_clients, 
    df_achats, 
    on='user_id',
    how='inner' // (Défaut)
)
// (Retourne user_id 2 et 3)
LEFT / RIGHT / OUTER

how='left' : Garde toutes les lignes du DataFrame de **gauche** (df_clients).

df_left = pd.merge(
    df_clients, 
    df_achats, 
    on='user_id',
    how='left'
)
// (Retourne user_id 1, 2, 3.
// 'achat' pour user_id 1 sera NaN)

// how='right' (Garde tout de 'df_achats')
// how='outer' (Garde tout de 1, 2, 3, 4)
5.1 Combinaison : pd.concat() (SQL UNION)

pd.concat() "empile" (stack) ou "colle" (join) des DataFrames.

axis=0 (Défaut) (UNION)

Empile les lignes (les DFs doivent avoir les mêmes colonnes).

df_jan = pd.read_csv("jan.csv")
df_fev = pd.read_csv("fev.csv")

// (Empile les lignes)
df_total = pd.concat(
    [df_jan, df_fev],
    axis=0,
    ignore_index=True // (Re-génère l'index 0,1,2...)
)
axis=1 (JOIN sur Index)

"Colle" les colonnes (les DFs doivent avoir le même index).

df_data = ...
df_labels = ... (indexés pareil)

// (Colle les colonnes)
df_total = pd.concat(
    [df_data, df_labels],
    axis=1
)
5.2 Vitrine (Qui utilise Pandas ?)

Pandas est l'outil **standard** de tout Data Scientist, Data Analyst, ou Ingénieur ML travaillant en Python. Il est la **fondation** du preprocessing pour le ML.

DomaineCas d'usage
Data Science (Général)Le "pain quotidien" : Charger un CSV, nettoyer (NaNs, types), agréger (groupby), et passer le .values (NumPy) à Scikit-learn.
FinTech / FinanceAnalyse de séries temporelles (resample, rolling), backtesting de stratégies, analyse de risque.
Business Intelligence (BI)Remplacement d'Excel pour l'analyse de ventes, KPIs, segmentation client.
Recherche (Académique)Nettoyage et analyse de données d'expérimentation avant visualisation (Matplotlib).
5.4 Cheat-sheet (Workflow)
1. Setup & Load
import pandas as pd
import numpy as np

df = pd.read_csv("data.csv")
2. Inspect
print(df.head())
print(df.info())
print(df.describe())
3. Select (Filter)
// Colonnes
df_sub = df[['col1', 'col2']]

// Lignes (label/position)
row_0 = df.iloc[0]
row_label = df.loc['idx_label']

// Filtre
df_filt = df[
    (df['age'] > 30) & 
    (df['ville'] != 'Paris')
]
4. Clean
// NaN
df['age'] = df['age'].fillna(df['age'].mean())
df = df.dropna() // Supprime lignes

// Types
df['age'] = df['age'].astype('int')
df['ville'] = df['ville'].astype('category')

// Doublons
df = df.drop_duplicates()
5. Manipulate
// Add Col
df['new_col'] = df['col1'] / df['col2']
df['cat'] = df['age'].apply(lambda x: 'A' if x > 30 else 'B')

// GroupBy (Split-Apply-Combine)
agg = df.groupby('ville').agg(
    age_mean=('age', 'mean'),
    count=('nom', 'count')
)

// Merge (JOIN)
df_merged = pd.merge(
    df, df_other, 
    on='key', 
    how='left'
)