Séance 3 : pandas, tables étiquetées (
DataFrame/Series,read_csv, index vs indice,loc/iloc, masques,NaN, TP « on the moon »). Clé de correction avec explications synthétiques. La lettre correspond à l’ordre des choix sur le sujet (A = 1er choix).
Clé de correction
| Q | Réponse | Rappel | Référence |
|---|---|---|---|
| 1 | A | pd.read_csv(..., sep=";", index_col="id") |
S3 slide « Charger et regarder : read_csv » · nb 2-01 § lecture d’un fichier csv · nb 2-01 § indexer les lignes |
| 2 | C | df["c"] → Series, df[["c"]] → DataFrame |
S3 slide « Les colonnes » · S3 slide « Les 3 pièges du jour » · nb 2-01 § accès aux colonnes avec df[] |
| 3 | B | info() : colonnes, valeurs non manquantes, dtype |
S3 slide « Charger et regarder : read_csv » · nb 2-04 § 4. info |
| 4 | D | len(df) = nombre de lignes = shape[0] |
S3 slide « Charger et regarder : read_csv » · nb 2-01 § forme et dimension de la table |
| 5 | A | loc = étiquettes (ligne, colonne) |
S3 slide « loc et iloc » · nb 2-03 § localisation avec loc et iloc |
| 6 | B | value_counts() → Series des occurrences, triée |
S3 slide « Les colonnes » · nb 2-02 § value_counts() |
| 7 | C | unique() renvoie les valeurs, len(...) en donne le nombre |
S3 slide « Les colonnes » (df["Embarked"].unique()) · nb 2-02 § exercice valeurs uniques |
| 8 | A | & + parenthèses |
S3 slide « Masques booléens » · nb 2-02 § structure d’un masque |
| 9 | D | df["Family"] = s ajoute une clé au « dictionnaire » des colonnes |
S3 slide « Les colonnes » · nb 2-03 § créer une nouvelle colonne |
| 10 | B | drop(columns=[...]) |
S3 slide « Nettoyer : drop, astype, to_numeric, replace » · nb 2-04 § 3. drop |
| 11 | C | accesseur .str : .str.contains(...) |
S3 slide « L’accesseur .str » · nb 2-04 § 15. memorial |
| 12 | D | isna().sum() : par colonne (axis=0 par défaut) |
S3 slide « Valeurs manquantes : NaN » · nb 2-02 § compter les valeurs manquantes |
| 13 | B | loc borne incluse (3), iloc exclue (2) |
S3 slide « loc et iloc » · S3 slide « Les 3 pièges du jour » · nb 2-03 § slicing avec loc par index |
| 14 | A | NaN est un flottant → float64 |
S3 slide « Valeurs manquantes : NaN » · S3 slide « Les 3 pièges du jour » · nb 2-01 § accès aux colonnes avec df[] |
| 15 | C | errors="coerce" → NaN, ignoré par sum() : 19.0 |
S3 slide « Nettoyer : drop, astype, to_numeric, replace » · nb 2-04 § 9. to_numeric |
| 16 | D | and sur des Series → ValueError |
S3 slide « Masques booléens » · nb 2-02 § structure d’un masque |
| 17 | A | modifier une sélection ne modifie pas df ; utiliser df.loc[...] = ... |
S3 slide « Écrire dans une table » · S3 slide « Les 3 pièges du jour » · nb 2-03 § modification d’une copie |
| 18 | B | loc[20, "b"] = 5 ; iloc[-1, 0] = 3 |
S3 slide « loc et iloc » · nb 2-03 § localisation avec loc et iloc · nb 2-03 § localiser une ligne ou une colonne |
| 19 | D | set_index("id") : id quitte les colonnes |
S3 slide « Index et indice » · nb 2-01 § indexer les lignes |
| 20 | C | fillna renvoie une nouvelle série ; sum() ignore les NaN |
S3 slide « Valeurs manquantes : NaN » · S3 slide « Les colonnes » · nb 2-02 § les fonctions numpy d’agrégation |
Q1
Où dans le cours : slide « Charger et regarder : read_csv » · nb 2-01 § lecture d’un fichier csv ; nb 2-01 § indexer les lignes (sep= n’apparaît dans le nb qu’en indice de l’exercice final)
Bonne réponse : A — pd.read_csv("f.csv", sep=";", index_col="id")
Pourquoi : le séparateur se règle avec sep= et la colonne d’index avec index_col=. separator=, index= et pd.open_csv n’existent pas ; read_table("f.csv", ";", index=0) passe le séparateur en positionnel (interdit) et index= n’existe pas.
Q2
Où dans le cours : slide « Les colonnes » ; slide « Les 3 pièges du jour » · nb 2-01 § accès aux colonnes avec df[] (point d’arrêt 1 du README)
Bonne réponse : C — une Series / une DataFrame à une colonne
Pourquoi : df["Age"] accède à une colonne (objet Series, 1 dimension) ; df[["Age"]] passe une liste de colonnes et renvoie donc une DataFrame (2 dimensions), même avec une seule colonne.
Q3
Où dans le cours : slide « Charger et regarder : read_csv » · nb 2-04 § 4. info (absent de 2-01, vu au TP)
Bonne réponse : B — nom, nombre de valeurs non manquantes (non-null) et dtype de chaque colonne
Pourquoi : c’est ce qu’on a utilisé dans le TP « on the moon » pour repérer une colonne entièrement vide. Les statistiques sont données par describe(), les premières lignes par head(), la forme par shape.
Q4
Où dans le cours : slide « Charger et regarder : read_csv » · nb 2-01 § forme et dimension de la table (len(df) utilisé dans les exercices de 2-03)
Bonne réponse : D — 891
Pourquoi : shape vaut (lignes, colonnes) ; len(df) est le nombre de lignes. 10692 serait df.size (891 × 12).
Q5
Où dans le cours : slide « loc et iloc » · nb 2-03 § localisation avec loc et iloc
Bonne réponse : A — df.loc[5, "Name"]
Pourquoi : loc prend les étiquettes dans l’ordre [ligne, colonne] : l’index 5 et la colonne "Name". iloc n’accepte que des positions entières ("Name" est refusé) ; df["Name", 5] chercherait une colonne nommée ("Name", 5) ; df.loc["Name", 5] inverse ligne et colonne.
Q6
Où dans le cours : slide « Les colonnes » · nb 2-02 § value_counts()
Bonne réponse : B — une Series indexée par les valeurs distinctes, avec leur nombre d’occurrences, triée par ordre décroissant
Pourquoi : value_counts() compte chaque modalité (ici S 644, C 168, Q 77). Le nombre de modalités s’obtient avec len(...unique()) (et, à partir de la S4, avec le raccourci nunique()) ; le nombre de valeurs non manquantes, avec count().
Q7
Où dans le cours : slide « Les colonnes » (df["Embarked"].unique()) · nb 2-02 § exercice valeurs uniques (l’énoncé demande de compter les valeurs uniques avec pd.Series.unique)
Bonne réponse : C — len(df["Pclass"].unique())
Pourquoi : unique() renvoie le tableau des valeurs distinctes ([3, 1, 2]) : c’est len(...) qui en donne le nombre (3). count() compte les valeurs non manquantes (891), len(df["Pclass"]) le nombre de lignes (891 aussi). Le raccourci nunique() fait la même chose en une méthode, mais on ne le rencontre qu’en S4 (nb 2-07).
Q8
Où dans le cours : slide « Masques booléens » · nb 2-02 § structure d’un masque
Bonne réponse : A — df[(df["Sex"] == "female") & (df["Age"] > 60)]
Pourquoi : comme en numpy, on combine des masques avec &, |, ~ et on parenthèse.
andlèveValueError(valeur de vérité d’uneSeriesambiguë).- Sans parenthèses,
"female" & df["Age"]est évalué d’abord, d’oùTypeError. "Sex" == "female"compare deux chaînes (False), pas des colonnes.
Q9
Où dans le cours : slide « Les colonnes » · nb 2-03 § créer une nouvelle colonne
Bonne réponse : D — df["Family"] = s
Pourquoi : une DataFrame se comporte comme un dictionnaire de colonnes : affecter une nouvelle clé crée la colonne.
df.Family = scrée un simple attribut Python sur l’objet, pas une colonne (pandas émet un avertissement).df[Family]:Familysans guillemets est une variable inexistante, d’oùNameError.add_columnn’existe pas.
Q10
Où dans le cours : slide « Nettoyer : drop, astype, to_numeric, replace » · nb 2-04 § 3. drop (le mot-clé columns= n’est que sur la slide)
Bonne réponse : B — df = df.drop(columns=["Cabin"])
Pourquoi : drop renvoie une nouvelle table (sauf inplace=True) ; il faut préciser columns= (ou axis=1). df.drop("Cabin") cherche une ligne d’index "Cabin", d’où KeyError. remove n’existe pas, del df.Cabin supprime un attribut, pas une colonne (del df["Cabin"] fonctionnerait).
Q11
Où dans le cours : slide « L’accesseur .str » · nb 2-04 § 15. memorial (étape 15 = « à finir chez soi » selon le README)
Bonne réponse : C — df[df["Name"].str.contains("Mrs")]
Pourquoi : les méthodes de chaînes s’appliquent à une colonne via l’accesseur .str ; contains renvoie un masque booléen. Sans .str, contains/find n’existent pas sur une Series ; "Mrs" in df["Name"] teste l’appartenance à l’index.
Q12
Où dans le cours : slide « Valeurs manquantes : NaN » · nb 2-02 § compter les valeurs manquantes
Bonne réponse : D — une Series : le nombre de valeurs manquantes de chaque colonne
Pourquoi : isna() renvoie une table de booléens de même forme ; sum() agrège par défaut sur axis=0 (on somme les lignes entre elles), d’où un résultat par colonne (Age 177, Cabin 687…). Le total s’obtient avec .sum().sum(), le compte par ligne avec sum(axis=1).
Q13
Où dans le cours : slide « loc et iloc » ; slide « Les 3 pièges du jour » · nb 2-03 § slicing avec loc par index
Bonne réponse : B — 3 2
Pourquoi : avec loc (étiquettes) la borne supérieure est incluse : "b":"d" donne b, c, d, soit 3 éléments. Avec iloc (positions) elle est exclue comme en Python : 1:3 donne les positions 1 et 2, soit 2 éléments.
Q14
Où dans le cours : slide « Valeurs manquantes : NaN » ; slide « Les 3 pièges du jour » · nb 2-01 § accès aux colonnes avec df[] (nb : on constate seulement Age en float64 ; l’explication est sur la slide + point d’arrêt 2 du README)
Bonne réponse : A — float64
Pourquoi : None devient NaN, et NaN est un flottant : toute la colonne est convertie en float64 (il n’y a pas de NaN entier classique). C’est pour cela que la colonne Age du Titanic est en flottants alors que ce sont des âges.
Q15
Où dans le cours : slide « Nettoyer : drop, astype, to_numeric, replace » · nb 2-04 § 9. to_numeric (le nb demande de « remplacer les invalides par NaN » sans nommer errors="coerce")
Bonne réponse : C — 19.0
Pourquoi : errors="coerce" remplace les valeurs non convertibles ("x") par NaN au lieu de lever une erreur ; sum() ignore les NaN par défaut : 12 + 7 = 19.0 (flottant à cause du NaN). Sans errors="coerce" on aurait bien ValueError.
Q16
Où dans le cours : slide « Masques booléens » · nb 2-02 § structure d’un masque
Bonne réponse : D — ValueError (« The truth value of a Series is ambiguous »)
Pourquoi : and demande la valeur de vérité de chaque Series entière, ce qui n’a pas de sens ; il faut & avec des parenthèses. Ce n’est ni équivalent à &, ni une table vide.
Q17
Où dans le cours : slide « Écrire dans une table » ; slide « Les 3 pièges du jour » · nb 2-03 § modification d’une copie
Bonne réponse : A — Non : sub se comporte comme une copie ; il faut écrire df.loc[df["Pclass"] == 1, "Age"] = 0
Pourquoi : une sélection par masque puis une affectation (chained indexing) modifie un objet intermédiaire, pas df. Les anciennes versions de pandas affichaient le SettingWithCopyWarning ; avec le copy-on-write (pandas ≥ 3) df n’est jamais modifié et aucune erreur n’est levée. La bonne façon de faire est toujours df.loc[masque, colonne] = valeur.
Q18
Où dans le cours : slide « loc et iloc » · nb 2-03 § localisation avec loc et iloc ; nb 2-03 § localiser une ligne ou une colonne
Bonne réponse : B — 5 3
Pourquoi : loc[20, "b"] utilise les étiquettes : ligne d’index 20, colonne b, soit 5. iloc[-1, 0] utilise les positions : dernière ligne (index 30), première colonne a, soit 3. Les étiquettes 10/20/30 ne sont pas des positions, d’où l’intérêt de bien distinguer loc et iloc.
Q19
Où dans le cours : slide « Index et indice » · nb 2-01 § indexer les lignes
Bonne réponse : D — (2, 1) ['v']
Pourquoi : set_index("id") transforme la colonne id en index des lignes : elle quitte les colonnes, il ne reste que v. Le nombre de lignes ne change pas (2). reset_index() ferait l’opération inverse.
Q20
Où dans le cours : slide « Valeurs manquantes : NaN » ; slide « Les colonnes » · nb 2-02 § les fonctions numpy d’agrégation (fillna et skipna ne sont que sur les slides ; aucun nb S3 n’utilise fillna)
Bonne réponse : C — 4.0 4.0
Pourquoi : s.fillna(0) renvoie une nouvelle série et son résultat n’est pas conservé : s contient toujours le NaN. Par défaut sum() ignore les NaN (skipna=True) : 1 + 3 = 4.0, que l’on enlève le NaN avec dropna() ou non. Pour modifier s, il faudrait s = s.fillna(0).
