Section 11.2.8 : pandas — DataFrames et manipulation de données
🎯 Objectif pédagogique
Maîtriser les DataFrames pandas pour charger, explorer et manipuler des données tabulaires. Vous serez capable de travailler avec des données structurées de manière aussi naturelle qu'avec un tableur — mais avec la puissance du code.
pandas — L'Excel du développeur
Marc a passé des années sur Excel. pandas est la réponse à toutes ses frustrations : pas de limite de lignes (Excel : 1M), pas de bugs de formules, reproductible, versionnable, et 100x plus rapide.
Créer un DataFrame
import pandas as pd
# Depuis un dictionnaire
data = \{
'company': ['Google', 'Meta', 'Stripe', 'Datadog', 'Mistral AI'],
'position': ['Frontend', 'React Dev', 'Full-Stack', 'Python Dev', 'ML Engineer'],
'status': ['interview', 'applied', 'offer', 'rejected', 'applied'],
'salary': [75000, 80000, 70000, 65000, 90000],
'date': ['2026-03-01', '2026-03-05', '2026-02-15', '2026-02-01', '2026-03-15']
\}
df = pd.DataFrame(data)
print(df)
Résultat :
company position status salary date
0 Google Frontend interview 75000 2026-03-01
1 Meta React Dev applied 80000 2026-03-05
2 Stripe Full-Stack offer 70000 2026-02-15
3 Datadog Python Dev rejected 65000 2026-02-01
4 Mistral AI ML Engineer applied 90000 2026-03-15
Explorer les données
df.head() # 5 premières lignes
df.tail(3) # 3 dernières lignes
df.shape # (5, 5) = 5 lignes, 5 colonnes
df.dtypes # Types de chaque colonne
df.info() # Résumé complet (types, nulls, mémoire)
df.describe() # Statistiques numériques (mean, std, min, max)
df.columns # Noms des colonnes
df.values # Array NumPy sous-jacent
Sélectionner des données
# Une colonne (→ Series)
df['company']
df.company # Notation point (si pas d'espace dans le nom)
# Plusieurs colonnes (→ DataFrame)
df[['company', 'salary']]
# Lignes par index
df.iloc[0] # Première ligne (par position)
df.iloc[1:3] # Lignes 2 et 3
df.loc[0] # Première ligne (par label)
# Cellule spécifique
df.iloc[0, 3] # Ligne 0, colonne 3 → 75000
df.at[0, 'salary'] # Plus rapide pour une cellule
Filtrer les données
# Filtre simple
interviews = df[df['status'] == 'interview']
print(interviews)
# Salaire > 70k
high_salary = df[df['salary'] > 70000]
# Conditions multiples (& = AND, | = OR)
good_options = df[(df['salary'] > 70000) & (df['status'] != 'rejected')]
# .query() — syntaxe plus lisible
good_options = df.query("salary > 70000 and status != 'rejected'")
# .isin() — équivalent de IN en SQL
active = df[df['status'].isin(['applied', 'interview'])]
# Recherche texte
google = df[df['company'].str.contains('Google', case=False)]
Ajouter et modifier des colonnes
# Nouvelle colonne calculée
df['monthly_salary'] = df['salary'] / 12
# Colonne conditionnelle
df['is_good'] = df['salary'] > 70000
# apply() — transformation personnalisée
def categorize_salary(s):
if s >= 80000: return 'excellent'
if s >= 60000: return 'bon'
return 'moyen'
df['salary_category'] = df['salary'].apply(categorize_salary)
# Convertir les dates
df['date'] = pd.to_datetime(df['date'])
df['month'] = df['date'].dt.month
df['day_of_week'] = df['date'].dt.day_name()
Trier et agréger
# Trier
df.sort_values('salary', ascending=False)
df.sort_values(['status', 'salary'], ascending=[True, False])
# Agréger (comme GROUP BY en SQL)
df.groupby('status')['salary'].mean()
# status
# applied 85000.0
# interview 75000.0
# offer 70000.0
# rejected 65000.0
# Agrégation multiple
df.groupby('status').agg(
count=('company', 'count'),
avg_salary=('salary', 'mean'),
max_salary=('salary', 'max')
)
pandas vs SQL — quel rapport ?
pandas et SQL font souvent la même chose :
- →
df[df['status'] == 'interview']=WHERE status = 'interview' - →
df.groupby('status')['salary'].mean()=GROUP BY status ... AVG(salary) - →
df.sort_values('salary')=ORDER BY salary
La différence : SQL travaille sur la base de données, pandas en mémoire. Si les données tiennent en RAM, pandas est souvent plus flexible.
🏋️ Exercice pratique (25 minutes)
import pandas as pd
# Charger depuis un CSV (créez d'abord le fichier ou utilisez le dict ci-dessus)
df = pd.DataFrame(\{
'company': ['Google','Meta','Stripe','Datadog','Mistral AI','OVH','Vercel','BNP','Doctolib','Alan'],
'position': ['Frontend','React','Full-Stack','Python','ML','DevOps','Frontend','Data','Backend','Full-Stack'],
'status': ['interview','applied','offer','rejected','applied','applied','interview','interview','applied','offer'],
'salary': [75000,80000,70000,65000,90000,45000,85000,55000,60000,72000],
'date': pd.to_datetime(['2026-03-01','2026-03-05','2026-02-15','2026-02-01','2026-03-15',
'2026-03-10','2026-03-12','2026-02-20','2026-03-08','2026-01-20'])
\})
# Exercices :
# 1. Combien de candidatures par statut ?
# 2. Salaire moyen des candidatures en entretien vs les offres
# 3. Quelles entreprises proposent > 80k ?
# 4. Ajoutez une colonne 'quarter' basée sur la date
# 5. Top 3 des salaires les plus élevés
Quelle est la différence entre df.iloc[0] et df.loc[0] ?
Comment filtrer un DataFrame pour les lignes où salary > 70000 ET status = 'applied' ?
Que fait df.groupby('status')['salary'].mean() ?