Tutoriel pandas
Apprenez pandas : Series, DataFrames, filtrage, groupby, valeurs manquantes, fusion et visualisation de données avec des exemples Python clairs.
pandas est la bibliothèque Python la plus utilisée pour travailler avec des données structurées (tabulaires). Elle fournit deux structures de données fondamentales — Series et DataFrame — ainsi qu'un riche ensemble d'outils pour charger, nettoyer, transformer, agréger et visualiser des données.
Ce chapitre couvre tout ce dont vous avez besoin pour passer de zéro à productif avec pandas : installation, structures de données, lecture de fichiers, sélection et filtrage de données, gestion des valeurs manquantes, regroupement, fusion et tracé de graphiques de base.
Installer pandas
Installez pandas avec pip :
pip install pandasSi vous souhaitez suivre les exemples de tracé plus loin dans ce chapitre, installez également Matplotlib :
pip install matplotlibAprès l'installation, importez pandas avec l'alias conventionnel pd :
import pandas as pdLes deux structures de données fondamentales
Series
Une Series est un tableau unidimensionnel étiqueté. Chaque élément possède une valeur et une étiquette d'index correspondante (par défaut, des entiers commençant à 0).
import pandas as pd
scores = pd.Series([88.5, 92.0, 79.5, 95.0])
print(scores)Résultat :
0 88.5
1 92.0
2 79.5
3 95.0
dtype: float64Vous pouvez fournir des étiquettes d'index personnalisées pour rendre les données auto-descriptives :
scores = pd.Series(
[88.5, 92.0, 79.5, 95.0],
index=['Alice', 'Bob', 'Carol', 'Dave']
)
print(scores)
print(scores['Bob']) # 92.0Résultat :
Alice 88.5
Bob 92.0
Carol 79.5
Dave 95.0
dtype: float64
92.0Une Series avec un index significatif est similaire à un dictionnaire Python, mais elle supporte les opérations vectorisées et est intégrée au reste de l'API pandas.
DataFrame
Un DataFrame est un tableau bidimensionnel avec des lignes et des colonnes étiquetées — imaginez-le comme une feuille de calcul ou une table SQL chargée dans Python. Chaque colonne est en interne une Series qui partage le même index de lignes.
Créer un DataFrame à partir d'un dictionnaire de listes
Résultat :
name age score
0 Alice 25 88.5
1 Bob 30 92.0
2 Carol 28 79.5
3 Dave 35 95.0Les clés du dictionnaire deviennent les noms de colonnes ; les valeurs du dictionnaire deviennent les colonnes. L'index de lignes est par défaut 0, 1, 2, 3.
Attributs utiles pour inspecter un DataFrame juste après sa création :
| Attribut / Méthode | Ce qu'il retourne |
|---|---|
df.shape | Tuple de (rows, columns) |
df.dtypes | Type de données de chaque colonne |
df.columns | Étiquettes des colonnes |
df.index | Étiquettes des lignes |
df.head(n) | Les n premières lignes (par défaut 5) |
df.tail(n) | Les n dernières lignes (par défaut 5) |
df.describe() | Statistiques récapitulatives pour les colonnes numériques |
df.info() | Noms de colonnes, types et nombre de valeurs non nulles |
Lire des données depuis des fichiers
Dans de vrais projets, vous créez rarement des DataFrames à la main. pandas peut lire des dizaines de formats de fichiers.
Lire un fichier CSV
import pandas as pd
df = pd.read_csv('sales.csv')
print(df.head())
print(df.shape) # e.g. (1000, 5)
print(df.dtypes)pd.read_csv() infère automatiquement les types de colonnes. Options courantes :
sep=';'— changer le délimiteur (par défaut la virgule)index_col='id'— utiliser une colonne comme index de lignesparse_dates=['date']— interpréter une colonne comme datetimenrows=500— lire uniquement les 500 premières lignes (utile pour les gros fichiers)
Lire un fichier Excel
df = pd.read_excel('report.xlsx', sheet_name='Sheet1')Nécessite la dépendance optionnelle openpyxl : pip install openpyxl.
Écrire des données dans un fichier
df.to_csv('output.csv', index=False) # CSV without the row index column
df.to_excel('output.xlsx', index=False) # ExcelSélectionner des données
Sélectionner des colonnes
Sélectionnez une seule colonne pour obtenir une Series :
ages = df['age']
print(type(ages)) # <class 'pandas.core.series.Series'>Sélectionnez plusieurs colonnes pour obtenir un DataFrame :
subset = df[['name', 'score']]
print(subset)Résultat :
name score
0 Alice 88.5
1 Bob 92.0
2 Carol 79.5
3 Dave 95.0Sélectionner des lignes avec loc et iloc
pandas propose deux sélecteurs de lignes principaux :
loc— sélectionner par étiquette (valeur d'index)iloc— sélectionner par position entière (base 0)
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
print(df.loc[1]) # row with index label 1
print()
print(df.iloc[0]) # first row by position
print()
print(df.loc[1:2]) # rows with labels 1 and 2 (inclusive)
print()
print(df.iloc[0:2]) # rows at positions 0 and 1 (end is exclusive)Résultat :
name Bob
age 30
score 92.0
Name: 1, dtype: object
name Alice
age 25
score 88.5
Name: 0, dtype: object
name age score
1 Bob 30 92.0
2 Carol 28 79.5
name age score
0 Alice 25 88.5
1 Bob 30 92.0Notez la différence : loc[1:2] est basé sur les étiquettes et inclusif des deux côtés ; iloc[0:2] est basé sur la position et exclusif à droite (comme les tranches Python classiques).
Vous pouvez également sélectionner une cellule spécifique :
print(df.loc[1, 'score']) # 92.0 — by label
print(df.iloc[0, 2]) # 88.5 — by positionFiltrer des lignes
Filtrez les lignes en utilisant une condition booléenne entre crochets :
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
# Rows where age is greater than 28
print(df[df['age'] > 28])Résultat :
name age score
1 Bob 30 92.0
3 Dave 35 95.0Combinez plusieurs conditions avec & (et) ou | (ou). Enveloppez toujours chaque condition entre parenthèses :
# Age > 25 AND score >= 90
print(df[(df['age'] > 25) & (df['score'] >= 90)])Résultat :
name age score
1 Bob 30 92.0
3 Dave 35 95.0Utilisez isin() pour filtrer par une liste de valeurs :
print(df[df['name'].isin(['Alice', 'Carol'])])Ajouter et modifier des colonnes
Ajoutez une nouvelle colonne en lui faisant une affectation :
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
# Add a column with a calculated value
df['grade'] = df['score'].apply(lambda x: 'A' if x >= 90 else 'B')
print(df)Résultat :
name age score grade
0 Alice 25 88.5 B
1 Bob 30 92.0 A
2 Carol 28 79.5 B
3 Dave 35 95.0 Aapply() exécute une fonction sur chaque élément d'une colonne. Pour une arithmétique simple, vous pouvez utiliser directement des opérations vectorisées — elles sont plus rapides qu'apply() :
df['score_scaled'] = df['score'] / 100 # no apply() neededRenommez des colonnes avec rename() :
df = df.rename(columns={'score': 'exam_score', 'age': 'years_old'})Supprimez une colonne avec drop() :
df = df.drop(columns=['grade'])Trier des données
Triez un DataFrame sur une ou plusieurs colonnes avec sort_values() :
import pandas as pd
data = {
'department': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
'name': ['Alice', 'Bob', 'Carol', 'Dave', 'Eve'],
'salary': [90000, 95000, 70000, 72000, 88000],
}
df = pd.DataFrame(data)
print(df.sort_values('salary', ascending=False))Résultat :
department name salary
1 Eng Bob 95000
0 Eng Alice 90000
4 Eng Eve 88000
3 HR Dave 72000
2 HR Carol 70000Triez sur plusieurs colonnes — par exemple, département en ordre croissant, puis salaire décroissant au sein de chaque département :
df_sorted = df.sort_values(['department', 'salary'], ascending=[True, False])
print(df_sorted)Gérer les valeurs manquantes
Les jeux de données réels contiennent presque toujours des valeurs manquantes. pandas les représente sous forme de NaN (Not a Number).
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, None, 28, 35],
'score': [88.5, 92.0, None, 95.0],
}
df = pd.DataFrame(data)
# Count missing values per column
print(df.isnull().sum())Résultat :
name 0
age 1
score 1
dtype: int64Remplir les valeurs manquantes
Remplacez NaN par une valeur fixe ou une statistique :
df_filled = df.fillna({
'age': df['age'].mean(), # fill with column mean
'score': df['score'].median() # fill with column median
})
print(df_filled)Résultat :
name age score
0 Alice 25.000000 88.5
1 Bob 29.333333 92.0
2 Carol 28.000000 92.0
3 Dave 35.000000 95.0Supprimer les lignes avec des valeurs manquantes
df_dropped = df.dropna()
print(df_dropped)Résultat :
name age score
0 Alice 25.0 88.5
3 Dave 35.0 95.0Quand remplir et quand supprimer : supprimer des lignes fait perdre des données et peut introduire un biais si les valeurs ne sont pas manquantes au hasard. Le remplissage (imputation) est généralement préférable lorsque les données manquantes sont rares. Pour les workflows d'apprentissage automatique, consultez le chapitre Scale pour normaliser les caractéristiques numériques après imputation.
Regrouper des données
groupby() divise le DataFrame en groupes, applique une fonction à chaque groupe et combine les résultats. C'est l'équivalent pandas de GROUP BY en SQL.
import pandas as pd
data = {
'department': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
'name': ['Alice', 'Bob', 'Carol', 'Dave', 'Eve'],
'salary': [90000, 95000, 70000, 72000, 88000],
}
df = pd.DataFrame(data)
print(df.groupby('department')['salary'].mean())Résultat :
department
Eng 91000.0
HR 71000.0
Name: salary, dtype: float64Appliquez plusieurs fonctions d'agrégation à la fois avec agg() :
print(df.groupby('department')['salary'].agg(['mean', 'min', 'max', 'count']))Résultat :
mean min max count
department
Eng 91000.0 88000 95000 3
HR 71000.0 70000 72000 2Fusionner et concaténer des DataFrames
Fusionner (comme un SQL JOIN)
Utilisez pd.merge() pour combiner deux DataFrames sur une colonne clé commune :
import pandas as pd
employees = pd.DataFrame({
'emp_id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Carol'],
'dept_id': [10, 20, 10],
})
departments = pd.DataFrame({
'dept_id': [10, 20],
'dept_name': ['Engineering', 'HR'],
})
merged = pd.merge(employees, departments, on='dept_id')
print(merged)Résultat :
emp_id name dept_id dept_name
0 1 Alice 10 Engineering
1 2 Bob 20 HR
2 3 Carol 10 EngineeringPar défaut, il s'agit d'une jointure interne (inner join) (seules les lignes avec une clé correspondante dans les deux DataFrames). Contrôlez le type de jointure avec how :
how='left'— toutes les lignes du DataFrame gauche, les lignes correspondantes du droithow='right'— toutes les lignes du DataFrame droit, les lignes correspondantes du gauchehow='outer'— toutes les lignes des deux DataFrames ;NaNlà où il n'y a pas de correspondance
Concaténer (empiler des DataFrames)
Utilisez pd.concat() pour empiler verticalement des DataFrames avec les mêmes colonnes :
import pandas as pd
q1 = pd.DataFrame({'name': ['Alice', 'Bob'], 'sales': [120, 95]})
q2 = pd.DataFrame({'name': ['Carol', 'Dave'], 'sales': [110, 130]})
combined = pd.concat([q1, q2], ignore_index=True)
print(combined)Résultat :
name sales
0 Alice 120
1 Bob 95
2 Carol 110
3 Dave 130ignore_index=True réinitialise l'index de lignes pour qu'il aille de 0 à 3 au lieu de répéter 0 et 1 de chaque DataFrame source.
Statistiques descriptives
pandas facilite le calcul de statistiques récapitulatives sur l'ensemble d'un DataFrame ou sur des colonnes individuelles :
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 30, 28, 35],
'score': [88.5, 92.0, 79.5, 95.0],
}
df = pd.DataFrame(data)
print(df[['age', 'score']].describe())Résultat :
age score
count 4.000000 4.000000
mean 29.500000 88.750000
std 4.203173 6.714412
min 25.000000 79.500000
25% 27.250000 86.250000
50% 29.000000 90.250000
75% 31.250000 92.750000
max 35.000000 95.000000Des statistiques individuelles sont également disponibles sous forme de méthodes directes : df['score'].mean(), df['score'].std(), df['score'].median(), df['age'].max().
Visualisation de données de base
pandas s'intègre avec Matplotlib pour vous permettre de tracer directement depuis un DataFrame avec la méthode .plot(). Installez Matplotlib d'abord si ce n'est pas déjà fait : pip install matplotlib.
Graphique en ligne
import pandas as pd
import matplotlib.pyplot as plt
data = {
'month': ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
'revenue': [15000, 18000, 16500, 21000, 23000],
}
df = pd.DataFrame(data)
df.plot(kind='line', x='month', y='revenue', marker='o', title='Monthly Revenue')
plt.ylabel('Revenue ($)')
plt.tight_layout()
plt.show()Graphique en barres
df.plot(kind='bar', x='month', y='revenue', color='steelblue', title='Monthly Revenue')
plt.ylabel('Revenue ($)')
plt.xticks(rotation=0)
plt.tight_layout()
plt.show()Valeurs courantes pour le paramètre kind :
kind | Type de graphique |
|---|---|
'line' | Graphique en ligne |
'bar' | Graphique en barres verticales |
'barh' | Graphique en barres horizontales |
'hist' | Histogramme |
'box' | Boîte à moustaches |
'scatter' | Nuage de points (nécessite x et y) |
'pie' | Diagramme circulaire |
Pour des tracés plus avancés, consultez les chapitres Matplotlib Introduction et Matplotlib Scatter Plot.
Pièges courants
SettingWithCopyWarning : lorsque vous filtrez un DataFrame puis essayez de modifier le résultat, pandas peut vous avertir que vous modifiez une copie plutôt que l'original. Utilisez .copy() pour être explicite :
# Safe: work on an explicit copy
young = df[df['age'] < 30].copy()
young['group'] = 'junior'Indexage chaîné : df['col'][0] = value peut ou non modifier le DataFrame original. Utilisez toujours df.loc[0, 'col'] = value pour les affectations.
Noms de colonnes avec des espaces : si une colonne est nommée "first name", vous devez utiliser la notation entre crochets — df['first name'] — et non la notation pointée (df.first name est une erreur de syntaxe).
Entier vs. flottant après fillna : remplir NaN dans une colonne entière avec un nombre promeut la colonne en float64 car NaN est un flottant. Utilisez pd.Int64Dtype() (entier nullable) si vous avez besoin de conserver la sémantique entière avec des valeurs manquantes.
Chapitres connexes
- NumPy Tutorial — la bibliothèque de tableaux sur laquelle pandas est construit
- Matplotlib Introduction — créer des graphiques de qualité publication à partir de vos données
- Matplotlib Scatter Plot — visualiser les relations entre deux variables numériques
- Data Distribution — comprendre comment les valeurs se répartissent dans un jeu de données
- Scale — normaliser et standardiser les caractéristiques numériques avant la modélisation
- Categorical Data — encoder les colonnes non numériques pour l'apprentissage automatique
- Train/Test Split — diviser un DataFrame pandas en ensembles d'entraînement et de test
- SciPy Tutorial — fonctions statistiques et scientifiques qui complètent pandas