Écrire une table croisée
Exercice supplémentaire · niveau 2 · NSI (première), chapitre 6 — Traiter des données en tables · Données sales et formats mal formés
Énoncé
Écrire une table croisée : effectif par couple (classe, option). Quel contrôle simple valide le résultat ?
Corrigé
def croiser(table, lig, col):
"""Effectifs par couple de valeurs : un dictionnaire de dictionnaires.
Postcondition : la somme de tous les effectifs vaut len(table).
"""
res = {}
for ligne in table:
res.setdefault(ligne[lig], {})
v = ligne[col]
res[ligne[lig]][v] = res[ligne[lig]].get(v, 0) + 1
return res
croiser(eleves, "classe", "option")
# {'1G3': {'NSI': 2}, '1G1': {'SVT': 1, 'SES': 1}, '1G2': {'NSI': 1}}
Le contrôle. La somme de toutes les cases doit valoir le nombre de lignes : chaque ligne est comptée dans une case et une seule.
assert sum(sum(d.values()) for d in croise.values()) == len(table)
Ici . C'est le même argument de partition que pour l'index multiple, et il attrape la même famille d'erreurs.
Ce que le croisement montre et qu'une colonne seule cache. Les effectifs par classe (, , ) et par option ( NSI, SVT, SES) ne disent pas que la 1G3 est entièrement en NSI. Seul le croisement le fait voir. C'est l'opération de base de toute analyse de données — et le tableau qu'on obtiendrait en terminale d'une requête GROUP BY sur deux colonnes.
Le creux du tableau. Les couples d'effectif nul n'apparaissent pas : il n'y a pas de clé 'SVT' sous '1G3'. Pour un affichage rectangulaire, il faut les ajouter à zéro — et get(v, 0) est le geste qui évite la KeyError à la lecture.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.