Aller au contenu

Bloc B — Traiter un jeu de données⚓︎

Au programme

Découper un CSV · extraire une colonne · réutiliser les fonctions de M0 · filtrer, trier, compter · lire une réponse d'API

Séances 2 et 3

Séance 2 : charger et explorer un jeu de données. Séance 3 : l'interroger pour répondre à une question.

Le jeu de données⚓︎

Recopie ce bloc en tête de tous tes programmes du module :

🐍 Script Python
donnees = """prenom,maths,francais,ecran
Camille,12,14,180
Lou,8,11,240
Mohamed,15,13,90
Sarah,17,16,120
Tom,9,7,300
Ines,11,15,150
Noah,14,12,210
Lea,6,10,270
Gabriel,18,15,60
Jade,13,14,165"""

Les triples guillemets

"""...""" permet d'écrire une chaîne sur plusieurs lignes. C'est le contenu exact d'un fichier CSV, collé dans le programme.

On procède ainsi pour éviter les questions de fichiers, qui n'apprennent rien d'intéressant. Le traitement, lui, est identique.

Découper le CSV⚓︎

Deux opérations suffisent, et tu connais déjà la logique depuis M0.

Activité 1 — De la chaîne à la table

Teste et observe :

🐍 Script Python
lignes = donnees.split("\n")
print(len(lignes))
print(lignes[0])
print(lignes[1])

Puis :

🐍 Script Python
print(lignes[1].split(","))
Réponse
📋 Texte
11
prenom,maths,francais,ecran
Camille,12,14,180
['Camille', '12', '14', '180']

split(separateur) découpe une chaîne et renvoie une liste.

  • donnees.split("\n") découpe sur les retours à la ligne → une ligne par élément.
  • ligne.split(",") découpe sur les virgules → une valeur par élément.

11 lignes et non 10 : la première contient les en-têtes.

Tout est du texte

Regarde bien : '12' est entre guillemets. Après un split, toutes les valeurs sont des chaînes de caractères, même les nombres.

C'est exactement le problème rencontré avec input() en M0. Et la solution est la même : convertir avec int() ou float().

Construire la table⚓︎

🐍 Script Python
lignes = donnees.split("\n")
entetes = lignes[0].split(",")

table = []
for ligne in lignes[1:]:
    table.append(ligne.split(","))
📋 Texte
>>> entetes
['prenom', 'maths', 'francais', 'ecran']
>>> table[0]
['Camille', '12', '14', '180']
>>> len(table)
10

lignes[1:] : le slicing resurgit

On saute la première ligne (les en-têtes) et on garde tout le reste. C'est la notation vue en M0.

Extraire une colonne⚓︎

À toi de jouer B.1 ⭐⭐

Écris une fonction colonne(table, indice) qui renvoie la liste des valeurs d'une colonne donnée.

📋 Texte
>>> colonne(table, 0)
['Camille', 'Lou', 'Mohamed', ...]
Corrigé
🐍 Script Python
def colonne(table, indice):
    resultat = []
    for ligne in table:
        resultat.append(ligne[indice])
    return resultat

C'est le schéma de construction de liste vu en M0 : liste vide → append dans la boucle → renvoyer.

À toi de jouer B.2 ⭐⭐ — Convertir

Écris une fonction en_nombres(liste) qui transforme une liste de chaînes en liste d'entiers.

Corrigé
🐍 Script Python
def en_nombres(liste):
    resultat = []
    for valeur in liste:
        resultat.append(int(valeur))
    return resultat

On peut maintenant enchaîner les deux :

🐍 Script Python
maths = en_nombres(colonne(table, 1))
ecran = en_nombres(colonne(table, 3))
print(maths)
print(ecran)
📋 Texte
[12, 8, 15, 17, 9, 11, 14, 6, 18, 13]
[180, 240, 90, 120, 300, 150, 210, 270, 60, 165]

Réutiliser M0 : les statistiques⚓︎

C'est ici que le module précédent paie. Colle tes fonctions de M0 dans ton programme — sans les modifier :

🐍 Script Python
def moyenne(liste):
    somme = 0
    for valeur in liste:
        somme = somme + valeur
    return somme / len(liste)


def maximum(liste):
    record = liste[0]
    for valeur in liste:
        if valeur > record:
            record = valeur
    return record

Activité 2 — Les premières statistiques

🐍 Script Python
print("Moyenne en maths :", round(moyenne(maths), 2))
print("Meilleure note   :", maximum(maths))
print("Écran moyen      :", round(moyenne(ecran), 1), "min/jour")
Résultat
📋 Texte
Moyenne en maths : 12.3
Meilleure note   : 18
Écran moyen      : 178.5 min/jour

Presque trois heures d'écran par jour en moyenne.

Attention à la moyenne

Cette moyenne cache des situations très différentes : de 60 à 300 minutes, soit du simple au quintuple. Une moyenne seule ne décrit pas une population — on y revient au bloc C.

À toi de jouer B.3 ⭐⭐ — Le minimum

Tu as maximum. Écris minimum(liste) sur le même modèle, puis affiche l'écart entre le plus gros et le plus petit temps d'écran.

Corrigé
🐍 Script Python
def minimum(liste):
    record = liste[0]
    for valeur in liste:
        if valeur < record:
            record = valeur
    return record


print("Écart :", maximum(ecran) - minimum(ecran), "minutes")
📋 Texte
Écart : 240 minutes

Le piège évité

On initialise avec liste[0], pas avec un nombre arbitraire — c'est exactement l'erreur du code C débusqué dans le bloc D de M0. La même vigilance sert ici.

Filtrer⚓︎

Filtrer, c'est ne garder que les lignes qui vérifient une condition.

À toi de jouer B.4 ⭐⭐

Écris une fonction filtrer(table, indice, seuil) qui renvoie les lignes dont la valeur de la colonne indice est supérieure ou égale à seuil.

Corrigé
🐍 Script Python
def filtrer(table, indice, seuil):
    resultat = []
    for ligne in table:
        if int(ligne[indice]) >= seuil:
            resultat.append(ligne)
    return resultat
🐍 Script Python
bons_en_maths = filtrer(table, 1, 12)
print(len(bons_en_maths), "élèves ont 12 ou plus")
print(colonne(bons_en_maths, 0))
📋 Texte
6 élèves ont 12 ou plus
['Camille', 'Mohamed', 'Sarah', 'Noah', 'Gabriel', 'Jade']

>= et non >

Encore le cas frontière du bloc D de M0 : avec >, les élèves ayant exactement 12 disparaîtraient.

Remarque aussi que filtrer renvoie une table, pas une liste de valeurs. On peut donc lui appliquer colonne juste après.

Trier⚓︎

À toi de jouer B.5 ⭐⭐⭐

Écris trier_par(table, indice) qui renvoie la table triée par ordre décroissant sur une colonne. Interdiction d'utiliser sorted ou .sort().

Indice : tu sais trouver un maximum. Que se passe-t-il si tu le retires, puis recommences ?

Corrigé

C'est le tri par sélection : on retire le maximum, on l'ajoute au résultat, on recommence.

🐍 Script Python
def trier_par(table, indice):
    reste = []
    for ligne in table:
        reste.append(ligne)

    resultat = []
    while len(reste) > 0:
        i_max = 0
        for i in range(len(reste)):
            if int(reste[i][indice]) > int(reste[i_max][indice]):
                i_max = i
        resultat.append(reste[i_max])
        reste.pop(i_max)
    return resultat
🐍 Script Python
classement = trier_par(table, 3)
for ligne in classement:
    print(ligne[0], ":", ligne[3], "min")
📋 Texte
Tom : 300 min
Lea : 270 min
Lou : 240 min
Noah : 210 min
Camille : 180 min
...

Pourquoi on copie la table d'abord

reste.pop() détruit la liste au fur et à mesure. Sans la copie, on abîmerait la table d'origine et les traitements suivants seraient faux.

C'est une règle générale : une fonction ne doit pas modifier ce qu'on lui donne, sauf si c'est explicitement son rôle.

Ce que ça coûte

Pour trier 10 lignes, ce tri fait une centaine de comparaisons. Pour un million de lignes, il en faudrait mille milliards. Les algorithmes de tri efficaces sont un grand sujet d'informatique — c'est au programme de NSI en première.

Répondre à une question⚓︎

À toi de jouer B.6 ⭐⭐⭐ — L'enquête

Réponds à ces trois questions en écrivant un programme, pas en lisant le tableau à l'œil :

  1. Combien d'élèves ont la moyenne dans les deux matières ?
  2. Quelle est la moyenne de temps d'écran des élèves qui ont moins de 10 en maths ? Et celle des autres ?
  3. Qui a le plus grand écart entre sa note de maths et celle de français ?
Corrigé
🐍 Script Python
# 1. Moyenne dans les deux matières
compteur = 0
for ligne in table:
    if int(ligne[1]) >= 10 and int(ligne[2]) >= 10:
        compteur = compteur + 1
print("1 -", compteur, "élèves ont la moyenne partout")

# 2. Comparer deux groupes
faibles = []
autres = []
for ligne in table:
    if int(ligne[1]) < 10:
        faibles.append(int(ligne[3]))
    else:
        autres.append(int(ligne[3]))
print("2 - moins de 10 en maths :", round(moyenne(faibles), 1), "min")
print("    les autres           :", round(moyenne(autres), 1), "min")

# 3. Le plus grand écart
record = 0
nom = ""
for ligne in table:
    ecart = int(ligne[1]) - int(ligne[2])
    if ecart < 0:
        ecart = -ecart
    if ecart > record:
        record = ecart
        nom = ligne[0]
print("3 -", nom, "avec un écart de", record, "points")
📋 Texte
1 - 7 élèves ont la moyenne partout
2 - moins de 10 en maths : 270.0 min
    les autres           : 139.3 min
3 - Ines avec un écart de 4 points

Question 3 : il y a une égalité

Ines (11 et 15) et Lea (6 et 10) ont toutes deux un écart de 4 points. Le programme n'en affiche qu'une : celle qu'il rencontre en premier, parce que la condition est ecart > record et non >=.

Ce n'est pas un bug, mais ce n'est pas anodin : ton programme a tranché une égalité sans te le dire. Sur un classement, une attribution de place ou une sélection, ce silence peut avoir des conséquences réelles.

Le piège de la question 2

Les élèves en difficulté en maths passent en moyenne bien plus de temps devant un écran. Beaucoup concluraient : les écrans font baisser les notes.

C'est une conclusion injustifiée. On observe que les deux vont ensemble ; on n'a montré aucun lien de cause à effet. Peut-être qu'une troisième cause explique les deux. Peut-être que ce sont les difficultés scolaires qui poussent vers les écrans, et non l'inverse.

Corrélation n'est pas causalité. On y revient au bloc C — c'est une des erreurs de raisonnement les plus répandues.

Lire une réponse d'API⚓︎

Une API est un service auquel un programme peut poser une question. La réponse arrive presque toujours en JSON.

Activité 3 — Décoder du JSON

🐍 Script Python
import json

reponse = '{"ville": "Mont-de-Marsan", "temperature": 18.5, "humidite": 72}'

releve = json.loads(reponse)

print(releve["ville"])
print(releve["temperature"], "°C")
Résultat
📋 Texte
Mont-de-Marsan
18.5 °C

json.loads transforme une chaîne JSON en structure Python exploitable. On accède ensuite à chaque champ par son nom, entre crochets.

Remarque : 18.5 est arrivé directement comme un nombre, sans conversion. Le JSON, contrairement au CSV, transporte les types. C'est son principal avantage.

À toi de jouer B.7 ⭐⭐

🐍 Script Python
reponse = '{"station": "MDM-04", "releves": [17.2, 18.5, 19.1, 18.8, 17.9]}'

Écris un programme qui affiche le nom de la station, le nombre de relevés, et la température moyenne.

Corrigé
🐍 Script Python
import json

reponse = '{"station": "MDM-04", "releves": [17.2, 18.5, 19.1, 18.8, 17.9]}'
data = json.loads(reponse)

print("Station :", data["station"])
print("Relevés :", len(data["releves"]))
print("Moyenne :", round(moyenne(data["releves"]), 2), "°C")
📋 Texte
Station : MDM-04
Relevés : 5
Moyenne : 18.3 °C

moyenne(), écrite en M0 pour des notes d'élèves, fonctionne sans une modification sur des températures venues d'une API. C'est tout l'intérêt d'écrire des fonctions.

Ce qu'il faut retenir⚓︎

L'essentiel du bloc B

  • split(separateur) découpe une chaîne en liste : c'est tout ce qu'il faut pour lire un CSV.
  • Après un split, tout est du texte — il faut convertir avant de calculer.
  • Filtrer garde des lignes, trier les réordonne, compter répond à une question.
  • Une fonction ne doit pas abîmer ce qu'on lui donne : on copie avant de détruire.
  • json.loads décode une réponse d'API — et le JSON, lui, transporte les types.
  • Corrélation n'est pas causalité : deux colonnes qui varient ensemble ne prouvent aucun lien de cause à effet.