🐼 Pandas – L'Analyse de Données en Python
Guide complet IDEO-Lab : DataFrame, Series, I/O, GroupBy, Merge & Preprocessing.
Vue d'ensemble
Data Analysis & Manipulation. (Excel/SQL en Python).
Data Science PythonPourquoi Pandas ?
Le DataFrame. Input pour Scikit-learn, TF, PyTorch.
Installation
pip install pandas. Dépend de NumPy. import pandas as pd.
Concept N°1 : Series (1D)
Une colonne de DataFrame. (Array NumPy + Index).
Series 1DConcept N°2 : DataFrame (2D)
Tableau (type Excel). Collection de Series (Colonnes).
I/O (Lecture & Écriture)
pd.read_csv, pd.read_excel, pd.read_sql. df.to_csv.
Inspection (Analyse)
.head(), .info(), .describe(), .shape, .columns.
Sélection N°1 : .loc[] (Label)
Sélection par **Nom** (label) de l'index et des colonnes.
.loc Label-basedSélection N°2 : .iloc[] (Index)
Sélection par **Position** (entier) [0, 1, 2...].
.iloc Integer-basedSélection N°3 : Masque Booléen
df[df['age'] > 30]. (Filtrage conditionnel).
Nettoyage : Données Manquantes
.isnull().sum(), .dropna(), .fillna().
Nettoyage : Types & Doublons
.astype() (ex: 'category'), .drop_duplicates().
Manipulation (Colonnes)
Ajouter (df['new']), Supprimer (.drop(axis=1)).
Manipulation (.apply)
Appliquer une fonction (ou lambda) à une colonne/ligne.
📊 Agrégation : .groupby()
Split-Apply-Combine. (.agg(), .mean(), .sum()).
Combinaison : merge()
Jointures (SQL JOINs : inner, left, right, outer).
Combinaison : concat()
"Empiler" des DataFrames (lignes: axis=0) (SQL UNION).
Vitrine (Qui l'utilise ?)
Standard de la Data Science (Spotify, Airbnb, Finance, R&D).
Data Science StandardLiens Utiles & Formation
pandas.pydata.org (User Guide), Cheat Sheets.
Cheat-sheet
Workflow (Read, Inspect, Select, Clean, GroupBy).
cheat WorkflowQu'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)
+-------------------------+
Pandas résout le problème des données "tabulaires" (structurées) en Python.
| Outil | Problème | Solution Pandas |
|---|---|---|
| Python (Listes/Dicts) | Lent. Pas d'opérations vectorisées. Complexe pour les agrégats. | Performances (via NumPy). API simple (.mean()). |
| Excel | Ne scale pas (limite de lignes). Non-reproductible (clics). | Gère des millions de lignes. Reproductible (scripts). |
| SQL | Orienté "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).
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__)
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
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)
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')
Une fois le df chargé, la première étape est de l'inspecter.
| Méthode / Attribut | Description |
|---|---|
.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()). |
.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']]
.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)
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]
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")
.astype) & DoublonsDoublons (.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')
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)
.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")
)
.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')
)
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)
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
)
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.
| Domaine | Cas 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 / Finance | Analyse 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). |
La documentation de Pandas est excellente, notamment le "User Guide".
| Site | Description |
|---|---|
| pandas.pydata.org | Le site officiel. Point d'entrée pour l'installation. |
| User Guide (Officiel) | La **RÉFÉRENCE ABSOLUE**. Un "livre" complet expliquant la théorie (.loc vs .iloc, groupby, merge...). |
| API Reference (Officiel) | Détail de chaque fonction (ex: tous les arguments de read_csv). |
| Stack Overflow (Tag: pandas) | Probablement le plus grand forum de questions/réponses sur Pandas. |
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'
)
