← Tous les corrigés

Q3passé le

Le sujet

Sujet du quiz (PDF)

Les questions à revoir sont listées sur votre page personnelle (lien reçu par mail), à côté de votre note.

Bilan de la classe

Copies
17
Moyenne
15.4
Médiane
15
Min – max
12 – 20
  • 12–142
  • 14–167
  • 16–187
  • 18–201

Ce qu'il faut retenir

  • Q19, ratée par 10 élèves sur 17 : set_index("id") fait passer id dans l'index des lignes ; elle quitte les colonnes, il ne reste que v, d'où (2, 1) ['v'].
  • Q12, ratée par 9 élèves : isna() donne une table de booléens et sum() agrège par défaut colonne par colonne. On obtient une Series (un compte par colonne), pas un entier.
  • Q14, ratée par 9 élèves : None devient NaN, et NaN est un flottant. Toute la colonne passe en float64, c'est pour ça que Age est en flottants dans le Titanic.
  • Q15, ratée par 8 élèves : errors="coerce" remplace "x" par NaN au lieu de lever une erreur, et sum() ignore les NaN : 12 + 7 = 19.0.

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.

  • and lève ValueError (valeur de vérité d’une Series ambiguë).
  • 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 = s crée un simple attribut Python sur l’objet, pas une colonne (pandas émet un avertissement).
  • df[Family] : Family sans guillemets est une variable inexistante, d’où NameError.
  • add_column n’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).