import pandas as pd
masse_moy = pd.Series([15.2, 21.5, 28.0],
index=["fuliginosa", "fortis", "magnirostris"])
print(masse_moy)fuliginosa 15.2
fortis 21.5
magnirostris 28.0
dtype: float64
DMI · FST · UCAD
NumPy calcule sur des tableaux de nombres. pandas, bâti sur NumPy, ajoute des colonnes nommées et des lignes étiquetées : le DataFrame, la table de données de la bio-informatique. On y manipule notre jeu de morphométrie de pinsons — cette fois avec une colonne espece. Exécutez chaque cellule avec Maj + Entrée. Les cellules À vous sont à compléter.
Une Series est une colonne : des valeurs avec une étiquette (l’index). Un DataFrame est un ensemble de colonnes partageant le même index — une table. On importe pandas sous le nom pd.
fuliginosa 15.2
fortis 21.5
magnirostris 28.0
dtype: float64
À vous. Créez une Series aile_moy valant [67.4, 74.8, 80.0] avec le même index des trois espèces, puis affichez-la.
On construit un DataFrame à partir d’un dictionnaire : chaque clé devient une colonne. Ici, 15 spécimens de 3 espèces, avec 4 mesures. head() en montre les premières lignes.
import numpy as np
data = {
"espece": ["fuliginosa"]*5 + ["fortis"]*6 + ["magnirostris"]*4,
"bec_long": [9.1, 9.4, 8.9, 9.6, 9.2, 12.8, 13.2, 12.5, 13.5, 12.9, 13.0, 16.1, 15.7, 16.5, 15.9],
"bec_haut": [8.0, 8.3, 7.8, 8.5, 8.1, 10.5, 10.9, 10.2, 11.1, 10.6, 10.7, 14.2, 13.8, 14.6, 14.0],
"aile": [67, 68, 66, 69, 67, 74, 75, np.nan, 76, 74, 75, 80, 79, 81, 80],
"masse": [15, 16, 14, 16, 15, 21, 22, 20, 23, 21, 22, 28, 27, 29, 28],
}
df = pd.DataFrame(data)
print(df.head()) espece bec_long bec_haut aile masse
0 fuliginosa 9.1 8.0 67.0 15
1 fuliginosa 9.4 8.3 68.0 16
2 fuliginosa 8.9 7.8 66.0 14
3 fuliginosa 9.6 8.5 69.0 16
4 fuliginosa 9.2 8.1 67.0 15
En pratique, les données arrivent souvent dans un fichier CSV. On sauvegarde avec to_csv et on recharge avec read_csv — le point de départ de presque toute analyse.
espece bec_long bec_haut aile masse
0 fuliginosa 9.1 8.0 67.0 15
1 fuliginosa 9.4 8.3 68.0 16
2 fuliginosa 8.9 7.8 66.0 14
3 fuliginosa 9.6 8.5 69.0 16
4 fuliginosa 9.2 8.1 67.0 15
À vous. Construisez un petit DataFrame oiseaux à partir du dictionnaire {"nom": ["merle", "pinson"], "taille": [24, 15]}, puis affichez-le.
Avant tout calcul, on regarde la table : shape (dimensions), info() (colonnes et types), describe() (résumé statistique des colonnes numériques).
<class 'pandas.DataFrame'>
RangeIndex: 15 entries, 0 to 14
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 espece 15 non-null str
1 bec_long 15 non-null float64
2 bec_haut 15 non-null float64
3 aile 14 non-null float64
4 masse 15 non-null int64
dtypes: float64(3), int64(1), str(1)
memory usage: 732.0 bytes
bec_long bec_haut aile masse
count 15.00 15.00 14.00 15.00
mean 12.55 10.75 73.64 21.13
std 2.75 2.41 5.36 5.18
min 8.90 7.80 66.00 14.00
25% 9.50 8.40 68.25 16.00
50% 12.90 10.60 74.50 21.00
75% 14.60 12.45 78.25 25.00
max 16.50 14.60 81.00 29.00
describe() livre d’un coup moyenne, écart-type, minimum, maximum et quartiles de chaque mesure. On remarque que aile n’a que 14 valeurs (count) au lieu de 15 : une mesure manque — on y reviendra.
À vous. Affichez la shape du DataFrame df, puis ses 3 premières lignes avec df.head(3).
Une colonne se prend par son nom : df["masse"] (c’est une Series). Plusieurs colonnes : une liste de noms. Une ligne se prend par son étiquette avec loc.
espece masse
0 fuliginosa 15
1 fuliginosa 16
2 fuliginosa 14
3 fuliginosa 16
4 fuliginosa 15
espece fuliginosa
bec_long 9.1
bec_haut 8.0
aile 67.0
masse 15
Name: 0, dtype: object
fuliginosa
À vous. Affichez la colonne bec_long (avec .head()), puis les deux colonnes espece et aile ensemble (avec .head()).
Comme avec NumPy, une comparaison produit un masque booléen ; placé entre crochets, il ne garde que les lignes qui vérifient la condition. Ici, les spécimens de plus de 25 g.
espece bec_long bec_haut aile masse
11 magnirostris 16.1 14.2 80.0 28
12 magnirostris 15.7 13.8 79.0 27
13 magnirostris 16.5 14.6 81.0 29
14 magnirostris 15.9 14.0 80.0 28
Tous les spécimens de plus de 25 g sont des magnirostris : le filtre a isolé la plus grande espèce, sans qu’on l’ait nommée.
À vous. Affichez les spécimens dont la bec_long est supérieure à 14 mm.
On calcule une nouvelle colonne à partir des colonnes existantes — l’opération est vectorisée, exactement comme avec NumPy. Ici, un rapport de forme du bec (longueur sur hauteur).
espece bec_long bec_haut rapport_bec
0 fuliginosa 9.1 8.0 1.14
1 fuliginosa 9.4 8.3 1.13
2 fuliginosa 8.9 7.8 1.14
3 fuliginosa 9.6 8.5 1.13
4 fuliginosa 9.2 8.1 1.14
À vous. Créez une colonne masse_mg égale à la masse convertie en milligrammes (df["masse"] * 1000), puis affichez df[["espece", "masse", "masse_mg"]].head().
sort_values("colonne") réordonne les lignes selon une colonne. Par défaut, du plus petit au plus grand.
espece bec_long bec_haut aile masse rapport_bec
2 fuliginosa 8.9 7.8 66.0 14 1.14
0 fuliginosa 9.1 8.0 67.0 15 1.14
4 fuliginosa 9.2 8.1 67.0 15 1.14
1 fuliginosa 9.4 8.3 68.0 16 1.13
3 fuliginosa 9.6 8.5 69.0 16 1.13
À vous. Affichez les lignes triées par bec_long (avec .head()).
Une mesure absente est notée NaN. isna() la repère, .sum() compte les valeurs manquantes. On peut ensuite supprimer les lignes concernées (dropna) ou combler le trou (fillna).
espece bec_long bec_haut aile masse rapport_bec
7 fortis 12.5 10.2 NaN 20 1.23
Une seule mesure manque : l’aile d’un fortis. Plutôt que de jeter toute la ligne, on peut combler le trou par la moyenne des ailes connues.
73.64
0
À vous. Comptez les valeurs manquantes de la colonne bec_long avec df["bec_long"].isna().sum().
value_counts() compte les occurrences de chaque valeur d’une colonne. groupby("espece") rassemble les lignes par espèce ; on applique ensuite une agrégation (mean, sum…) à chaque groupe.
espece
fortis 6
fuliginosa 5
magnirostris 4
Name: count, dtype: int64
espece
fortis 21.5
fuliginosa 15.2
magnirostris 28.0
Name: masse, dtype: float64
bec_long aile masse
espece
fortis 12.98 74.8 21.5
fuliginosa 9.24 67.4 15.2
magnirostris 16.05 80.0 28.0
En une ligne, groupby révèle le profil de chaque espèce : magnirostris a le bec le plus long, l’aile la plus grande et la masse la plus élevée ; fuliginosa est la plus petite sur les trois mesures. C’est exactement le genre de résumé qu’on cherche en analyse de données.
À vous. Affichez la hauteur de bec moyenne par espèce avec df.groupby("espece")["bec_haut"].mean().round(2).
df["masse"] (crochets simples). Avec une liste de noms, df[["espece", "masse"]], on obtient un DataFrame (crochets doubles).loc (étiquette) vs iloc (position) : df.loc[0] cible l’étiquette 0 ; df.iloc[0] la première ligne, quelle que soit son étiquette.NaN se propage : une valeur manquante n’est pas 0 ; il faut la traiter (dropna, fillna) avant certains calculs.df[df["masse"] > 25] renvoie une nouvelle vue ; pour garder le résultat, on l’affecte à une variable.pd.DataFrame({...}), read_csv, to_csv.shape, info(), describe(), head().df["col"], df[["c1", "c2"]], df.loc[...].df[df["col"] > v].sort_values("col").isna, dropna, fillna.value_counts(), groupby("col").mean().Prochaine séance — S8 : visualiser ces données (histogrammes, nuages de points) et faire le pont vers le Machine Learning.