đŒ Pandas
- Intro
- Explorer
- Filtrer / Trier
- Sélectionner
- Parcourir
- Nettoyer
- Transformer
- Statistiques
- Exporter
- Visualiser
- Activités
Ă la rencontre 10, nous avons appris Ă utiliser NumPy faire des calculs sur des tableaux de nombres. NumPy est puissant, mais il a une limite : il travaille sur des donnĂ©es dâun seul type (tous des nombres, ou tous des textes). Dans la rĂ©alitĂ©, un jeu de donnĂ©es scientifiques contient souvent des colonnes de types diffĂ©rents : des mesures numĂ©riques, des dates, des catĂ©gories, des noms. Pour manipuler ce genre de donnĂ©es, NumPy seul devient vite insuffisant :
import numpy as np
# Avec NumPy : difficile de mélanger des types
patient_ids = np.array(["P001", "P002", "P003", "P004"])
ages = np.array([34, 58, 45, 27])
glycemies = np.array([5.2, 7.8, 6.1, 4.9])
diagnostics = np.array(["normal", "diabete", "pre_diabete", "normal"])
# Pour filtrer les patients avec une glycémie élevée, il faut jongler entre 4 tableaux séparés...
masque = glycemies > 6.0
print(patient_ids[masque]) # ["P002" "P003"]
print(diagnostics[masque]) # ["diabete" "pre_diabete"]
Câest lĂ quâintervient đŒ Pandas : il regroupe toutes ces colonnes dans un seul objet, le DataFrame, et offre des outils pour les manipuler facilement.
Pour le TP2, vous devrez manipuler des donnĂ©es rĂ©elles. Voici les Ă©tapes typiques dâun pipeline dâanalyse, et les onglets qui y correspondent :
| Ătape | Ce quâon fait | Onglet |
|---|---|---|
| đ„ Charger | Importer un fichier CSV dans un DataFrame | Explorer |
| đ Filtrer | Filtrer et trier les donnĂ©es | Filtrer / Trier |
| đŻ SĂ©lectionner | Choisir des colonnes ou des lignes | SĂ©lectionner |
| đ Parcourir | ItĂ©rer sur les lignes ou colonnes | Parcourir |
| đ§č Nettoyer | GĂ©rer les valeurs manquantes et les doublons | Nettoyer |
| 𧟠Transformer | Créer de nouvelles colonnes | Transformer |
| đ Analyser | Calculer des statistiques, regrouper | Statistiques |
| đ€ Exporter | Enregistrer un DataFrame dans un fichier CSV | Exporter |
| đ Visualiser | Tracer des graphiques | Visualiser |
Pandas nâest quâune des bibliothĂšques utilisĂ©es en science des donnĂ©es.
Pour votre culture gĂ©nĂ©rale, voici lâĂ©cosystĂšme Python dans ce domaine :
- đŒ Pandas : manipulation de donnĂ©es tabulaires (câest le sujet de cette rencontre)
- đš Matplotlib : visualisation de donnĂ©es (on la connait dĂ©jĂ )
- đą NumPy : calcul scientifique sur des tableaux (vue Ă la rencontre 10)
- đ€ Scikit-learn : apprentissage automatique (prochain cours)
- đ§ Keras / TensorFlow : apprentissage profond (deep learning) (cours ultĂ©rieurs)
Les explications de cette section étaient-elles claires ?
On connait dĂ©jĂ les dictionnaires et les listes en Python. Un DataFrame Pandas, c'est exactement ça : un dictionnaire dont les valeurs sont des listes de mĂȘme longueur.
import pandas as pd
data = {
"patient_id": ["P001", "P002", "P003", "P004" ],
"age": [34, 58, 45, 27 ],
"glycemie_mmol_L": [5.2, 7.8, 6.1, 4.9 ],
"tension_systolique": [118, 142, 135, 112 ],
"diagnostic": ["normal", "diabete", "pre_diabete", "normal"],
}
df = pd.DataFrame(data)
print(df)
patient_id age glycemie_mmol_L tension_systolique diagnostic
0 P001 34 5.2 118 normal
1 P002 58 7.8 142 diabete
2 P003 45 6.1 135 pre_diabete
3 P004 27 4.9 112 normal
Quelques points importants Ă observer :
- Les clés du dictionnaire deviennent les noms des colonnes.
- Chaque liste devient une colonne de données.
- La colonne
0, 1, 2, 3à gauche est l'index (numéro de ligne automatique). - Chaque ligne est un enregistrement (ici, un patient).
dfest juste le nom de la variable qui stocke le DataFrame : on aurait pu l'appelerpatientsouplantesou n'importe quoi d'autre.
Un DataFrame peut avoir des milliers de lignes : c'est lĂ que Pandas devient indispensable, lĂ oĂč manipuler des listes et des dictionnaires Ă la main devient ingĂ©rable.
Sous le capot, chaque colonne d'un DataFrame est stockĂ©e comme un tableau NumPy (ndarray). C'est pour ça que Pandas hĂ©rite de la mĂȘme rapiditĂ© de calcul que NumPy, et que des opĂ©rations comme df["col"] * 2 fonctionnent sans boucle, exactement comme tableau * 2 en NumPy.
Dans l'exemple prĂ©cĂ©dent, les donnĂ©es Ă©taient Ă©crites directement dans le code. En pratique, les donnĂ©es proviennent presque toujours de fichiers externes : bases de donnĂ©es, exports Excel, JSON⊠Le format le plus courant est le CSV (Comma-Separated Values) : un simple fichier texte oĂč chaque ligne est un enregistrement et chaque valeur est sĂ©parĂ©e par un dĂ©limiteur (souvent une virgule).
Pandas permet de charger un fichier CSV en une seule ligne avec pd.read_csv(), qui retourne directement un DataFrame prĂȘt Ă ĂȘtre explorĂ©.
Le fichier tips_dataset.csv regroupe des données collectées dans un restaurant : pour chaque repas, on y retrouve le montant de la facture, le pourboire laissé, le jour, le moment de la journée, la taille du groupe, et quelques informations sur le serveur.
Téléchargez-le, placez-le à la racine d'un projet PyCharm, puis chargez-le :
import pandas as pd
df = pd.read_csv('tips_dataset.csv') # â retourne un DataFrame
Ces donnĂ©es serviront Ă illustrer toutes les opĂ©rations qui suivent! đŻ
df.head() retourne les 5 premiÚres lignes par défaut. On peut passer un nombre en argument pour en voir plus.
print(df.head()) # â les 5 premiĂšres lignes
print(df.head(20)) # â les 20 premiĂšres lignes
Résultat :
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
Si un DataFrame a trop de colonnes ou du contenu trop long, certaines colonnes peuvent ĂȘtre remplacĂ©es par des ....
Dans ce cas, on peut ajouter ces 2 instructions juste aprĂšs les importations en haut du script :
import pandas as pd
pd.set_option('display.max_colwidth', None)
pd.set_option('display.expand_frame_repr', False)
df.shape retourne un tuple (nombre de lignes, nombre de colonnes).
C'est la façon la plus rapide de connaßtre la taille d'un DataFrame.
print(df.shape) # â (244, 7)
print(df.shape[0]) # â 244 (nombre de lignes)
print(df.shape[1]) # â 7 (nombre de colonnes)
len(df) est une alternative Ă df.shape[0] pour obtenir uniquement le nombre de lignes.
print(len(df)) # â 244
print(df.shape[0]) # â 244 (mĂȘme rĂ©sultat)
df.columns retourne les noms des colonnes. On appelle .tolist() pour obtenir une liste Python ordinaire.
print(df.columns.tolist()) # â ['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size']
Dans un DataFrame, chaque colonne a un type de donnĂ©es (Dtype). On a dĂ©jĂ rencontrĂ© ce concept en NumPy avec tableau.dtype : c'est exactement la mĂȘme notion, appliquĂ©e Ă une colonne. Voici les types les plus courants et leur Ă©quivalent Python :
| Dtype Pandas | Ăquivalent Python | Description |
|---|---|---|
| int64 | int | Nombre entier |
| float64 | float | Nombre décimal |
| object | str | Texte (chaĂźne de caractĂšres) |
| bool | bool | Valeur booléenne (True / False) |
df.info() affiche le nombre de lignes, le nom et le Dtype de chaque colonne, et le nombre de valeurs non-nulles.
C'est souvent la premiÚre chose à appeler pour détecter des colonnes mal typées ou des valeurs manquantes.
df.info() # affiche directement â pas besoin de print()
Résultat :
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 244 entries, 0 to 243
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 total_bill 244 non-null float64
1 tip 244 non-null float64
2 sex 244 non-null object
3 smoker 244 non-null object
4 day 244 non-null object
5 time 244 non-null object
6 size 244 non-null int64
dtypes: float64(2), int64(1), object(3)
memory usage: 13.5+ KB
- RangeIndex: 244 entries â 244 lignes, indexĂ©es de 0 Ă 243
- float64 â nombre dĂ©cimal, aucune valeur manquante (244 non-null)
- object â texte (str en Python)
- int64 â nombre entier
- dtypes: float64(2), int64(1), object(3) â rĂ©sumĂ© des types prĂ©sents dans le DataFrame
df.describe() retourne un résumé statistique rapide pour toutes les colonnes numériques.
print(df.describe())
Résultat :
total_bill tip size
count 244.000000 244.000000 244.000000
mean 19.785943 2.998279 2.569672
std 8.902412 1.383638 0.951100
min 3.070000 1.000000 1.000000
25% 13.347500 2.000000 2.000000
50% 17.795000 2.900000 2.000000
75% 24.127500 3.562500 3.000000
max 50.810000 10.000000 6.000000
- count â nombre de valeurs non-nulles
- mean â moyenne
- std â Ă©cart-type (mesure la dispersion des valeurs)
- min / max â valeur minimale et maximale
- 25% / 50% / 75% â quartiles (50% = mĂ©diane)
Avant d'écrire du code, on peut explorer un fichier CSV directement dans PyCharm en faisant un double-clic dessus. Deux modes sont disponibles en bas de l'éditeur : Mode Text (contenu brut) et Mode Data (tableau interactif avec filtre, tri et recherche).

Mode Text - affichage brut du fichier

Mode Data - affichage tabulaire interactif
â ïž PyCharm (comme Excel, limitĂ© Ă ~1 million de lignes) n'affiche pas nĂ©cessairement toutes les lignes pour des raisons de performance. C'est prĂ©cisĂ©ment pourquoi Pandas est indispensable : il peut traiter des fichiers de plusieurs millions de lignes sans limitation.
| Opération | Syntaxe | Description |
|---|---|---|
| Importer Pandas | import pandas as pd | Convention universelle |
| Charger un CSV | df = pd.read_csv('fichier.csv') | Retourne un DataFrame |
| Aperçu des données | df_apercu = df.head(5) | Retourne les 5 premiÚres lignes |
| Dimensions | dimensions = df.shape | Retourne (244, 7) : lignes, colonnes |
| Nombre de lignes | n = len(df) | Retourne le nombre de lignes |
| Noms des colonnes | colonnes = df.columns.tolist() | Retourne une liste des noms de colonnes |
| Types et valeurs manquantes | df.info() | Affiche directement dans la console |
| Statistiques descriptives | df_stats = df.describe() | Retourne un DataFrame (colonnes numériques) |
Les explications de cette section étaient-elles claires ?
Filtrer un DataFrame, c'est ne garder que les lignes qui satisfont une condition, comme un tamis qui laisse passer certaines données et en retient d'autres.
Par exemple, sur un DataFrame de 244 repas dans un restaurant, on pourrait vouloir garder seulement :
- les repas oĂč le pourboire laissĂ© dĂ©passe 5 $
- les repas du dimanche soir
- les repas avec un groupe de plus de 4 personnes
Le résultat est toujours un nouveau DataFrame. Le DataFrame original df n'est pas modifié, et c'est pourquoi on va généralement stocker le résultat dans une nouvelle variable :
df_gros_pourboires = df[df["tip"] > 5]
Quand on écrit df[df["tip"] > 5], Pandas effectue deux étapes :
df["tip"] > 5produit une sĂ©rie de boolĂ©ens :Truepour chaque ligne oĂč le pourboire dĂ©passe 5,Falsesinondf[...]ne conserve que les lignes oĂč la valeur estTrue
C'est exactement la mĂȘme logique que les masques boolĂ©ens vus Ă la rencontre 10 : t[t > 5] en NumPy et df[df["tip"] > 5] en Pandas utilisent le mĂȘme mĂ©canisme. La seule diffĂ©rence : NumPy filtre des valeurs dans un tableau, Pandas filtre des lignes dans un DataFrame.
Par exemple, on pourrait trÚs bien d'abord créer le masque booléen, puis ensuite l'appliquer :
masque = df["tip"] > 5
df_gros_pourboires = df[masque]
Mais en général, on combine les deux étapes en une seule ligne pour plus de concision :
df_gros_pourboires = df[df["tip"] > 5]
print(df_gros_pourboires)
Résultat :
total_bill tip sex smoker day time size
23 39.42 7.58 Male No Sat Dinner 4
44 30.40 5.60 Male No Sun Dinner 4
47 32.40 6.00 Male No Sun Dinner 4
52 34.81 5.20 Female No Sun Dinner 4
59 48.27 6.73 Male No Sat Dinner 4
...
Un filtre simple compare les valeurs d'une colonne à une valeur de référence. On peut utiliser les opérateurs de comparaison habituels.
# Comparaison numérique
df_gros_pourboires = df[df["tip"] > 5] # pourboire supérieur à 5 $
df_petites_tables = df[df["size"] <= 2] # tables de 1 ou 2 personnes
df_facture_exacte = df[df["total_bill"] == 16.99] # montant exact
# Comparaison sur du texte (égalité exacte)
df_souper = df[df["time"] == "Dinner"] # repas du soir seulement
df_non_fumeurs = df[df["smoker"] == "No"] # tables non-fumeurs
df_samedi = df[df["day"] == "Sat"] # repas du samedi
Pour filtrer sur le contenu d'une colonne textuelle, Pandas offre des méthodes .str..
Elles sont utiles quand on veut chercher une sous-chaßne plutÎt que vérifier une égalité exacte.
df_jours_th = df[df["day"].str.contains("Th")] # "Thur" contient "Th"
df_jours_longs = df[df["day"].str.len() > 3] # "Thur" a 4 caractĂšres, "Fri" en a 3
df_majuscule_f = df[df["sex"].str.startswith("F")] # "Female" commence par "F"
On peut combiner plusieurs conditions avec & (ET) et | (OU). Chaque condition doit ĂȘtre entre parenthĂšses (comme avec NumPy).
# & : les deux conditions doivent ĂȘtre vraies
df_dimanche_souper = df[(df["day"] == "Sun") & (df["time"] == "Dinner")]
df_fumeurs_genereux = df[(df["smoker"] == "Yes") & (df["tip"] > 4)]
# | : au moins une des conditions doit ĂȘtre vraie
df_extremes_facture = df[(df["total_bill"] < 5) | (df["total_bill"] > 45)]
df_repas_courts = df[(df["time"] == "Lunch") | (df["size"] == 1)]
Sans parenthĂšses autour de chaque condition, Python interprĂšte mal l'expression et gĂ©nĂšre une erreur. Ăcris toujours (cond1) & (cond2), jamais cond1 & cond2. C'est la mĂȘme rĂšgle que pour les masques boolĂ©ens en NumPy : les parenthĂšses sont nĂ©cessaires lorsque plusieurs conditions sont combinĂ©es.
Quand on veut filtrer sur plusieurs valeurs d'une mĂȘme colonne, isin() est plus lisible qu'une suite de |.
# Garder seulement les repas du jeudi et du vendredi
df_jours_semaine = df[df["day"].isin(["Thur", "Fri"])]
# Garder seulement les grandes tables (4, 5 ou 6 personnes)
df_grandes_tables = df[df["size"].isin([4, 5, 6])]
isin() vs |df[df["day"].isin(["Thur", "Fri"])] est équivalent à df[(df["day"] == "Thur") | (df["day"] == "Fri")], mais beaucoup plus lisible quand la liste grandit.
Trier un DataFrame, c'est réordonner ses lignes selon les valeurs d'une ou plusieurs colonnes.
Par défaut, Pandas trie en ordre croissant (du plus petit au plus grand, ou de A à Z). On peut inverser cet ordre avec ascending=False.
sort_values() retourne un nouveau DataFrame trié. Le DataFrame original n'est pas modifié.
df_trie1 = df.sort_values(by="total_bill") # â ordre croissant par dĂ©faut
df_trie2 = df.sort_values(by="tip", ascending=False) # â ordre dĂ©croissant
df_trie3 = df.sort_values(by=["day", "total_bill"]) # â tri sur 2 colonnes
On peut chaĂźner un filtre et un tri en une seule instruction. Les deux versions ci-dessous produisent exactement le mĂȘme rĂ©sultat :
# Version détaillée : plus facile à lire et à déboguer
df_version1 = df[df["day"].isin(["Sun", "Sat"])]
df_version1 = df_version1.sort_values(by="total_bill")
# Version compacte ("Method Chaining") : une seule ligne
df_version2 = df[df["day"].isin(["Sun", "Sat"])].sort_values(by="total_bill")
Les deux contiennent les repas de fin de semaine, triés par montant de facture.
Plus tÎt on réduit la taille du jeu de données, plus les opérations suivantes sont rapides. Commencez toujours par filtrer avant de trier.
Quand on combine plusieurs opĂ©rations, il peut ĂȘtre difficile d'identifier la source d'une erreur. Le dĂ©bogage est souvent plus simple en dĂ©composant les instructions sur des lignes distinctes : cela permet de vĂ©rifier l'Ă©tat du DataFrame aprĂšs chaque transformation.
En mode débogage, PyCharm offre une fonctionnalité trÚs pratique : le lien "View as DataFrame", visible dans le panneau des variables. Il permet d'inspecter visuellement le contenu d'un DataFrame sous forme de tableau interactif, directement depuis le débogueur.

đ Cliquez sur "View as DataFrame" dans le panneau des variables pour inspecter un DataFrame en cours d'exĂ©cution.

đ Le contenu du DataFrame s'affiche dans une vue tabulaire claire, avec toutes ses lignes et colonnes.
| Opération | Syntaxe | Description |
|---|---|---|
| Importer Pandas | import pandas as pd | Convention universelle |
| Filtre simple (nombre) | df_filtrer = df[df["tip"] > 5] | Pourboire supérieur à 5 $ |
| Filtre simple (texte) | df_filtrer = df[df["time"] == "Dinner"] | ĂgalitĂ© exacte sur une colonne texte |
| Filtre texte (.str.) | df_filtrer = df[df["day"].str.contains("Th")] | Colonne contient une sous-chaĂźne |
| Filtre ET | df_filtrer = df[(df["day"] == "Sun") & (df["time"] == "Dinner")] | Les deux conditions vraies |
| Filtre OU | df_filtrer = df[(df["size"] == 1) | (df["size"] == 2)] | Au moins une condition vraie |
| Filtre liste | df_filtrer = df[df["day"].isin(["Thur", "Fri"])] | Valeur parmi une liste |
| Trier croissant | df_trier = df.sort_values(by="tip") | Du plus petit au plus grand |
| Trier décroissant | df_trier = df.sort_values(by="tip", ascending=False) | Du plus grand au plus petit |
| Trier multi-colonnes | df_trier = df.sort_values(by=["day", "tip"]) | Tri sur plusieurs colonnes |
| ChaĂźner filtre + tri | df_resultat = df[df["day"] == "Sun"].sort_values(by="tip") | Filtrer puis trier en une ligne |
Les explications de cette section étaient-elles claires ?
SĂ©lectionner, câest extraire une partie dâun DataFrame : certaines colonnes, certaines lignes, ou une cellule prĂ©cise. Câest diffĂ©rent de filtrer : filtrer choisit des lignes selon une condition, sĂ©lectionner choisit quelles colonnes ou positions on veut voir.
Selon ce quâon sĂ©lectionne, Pandas retourne lâun de ces trois types :
- DataFrame : un tableau Ă deux dimensions, comme
dflui-mĂȘme - Series : une seule colonne ou une seule ligne, câest-Ă -dire une liste de valeurs avec un index
- valeur scalaire : une seule valeur, comme un
intou unfloat
Le type retourné dépend aussi des crochets utilisés :
| Ce quâon sĂ©lectionne | Syntaxe | Type retournĂ© |
|---|---|---|
| Plusieurs colonnes | df[["col1", "col2"]] | DataFrame |
| Une seule colonne | df["col"] | Series |
| Une seule colonne (format tableau) | df[["col"]] | DataFrame |
| Plusieurs lignes (par position) | df.iloc[2:5] | DataFrame |
| Une seule ligne (par position) | df.iloc[3] | Series |
| Une cellule (par position) | df.iat[3, 0] | valeur scalaire (float, string, etc.) |
| Une cellule (par étiquette) | df.at[3, "tip"] | valeur scalaire (float, string, etc.) |
Lorsqu'on sélectionne une seule colonne d'un DataFrame, le résultat est une Series.
Lorsqu'on sélectionne une seule ligne, le résultat est aussi une Series.
Une Series ressemble Ă un dictionnaire parce quâelle associe une Ă©tiquette dâindex Ă chaque valeur :
- Dans une colonne, lâindex correspond aux lignes du DataFrame.
- Dans une ligne, lâindex correspond aux colonnes du DataFrame.
Mais une Series ressemble aussi Ă un tableau NumPy, parce quâon peut faire des opĂ©rations sur toutes ses valeurs dâun coup :
df["tip"] * 2
On peut donc voir une Series comme une colonne ou une ligne de données avec un index.
Câest un objet propre Ă Pandas, qui combine certaines idĂ©es du dictionnaire et du tableau numĂ©rique.