Exercices - Traitement de données en tables
Fichiers CSV et importation
Section intitulée « Fichiers CSV et importation »Exercice 1 - Lecture d'un fichier CSV
Section intitulée « Exercice 1 - Lecture d'un fichier CSV »On dispose du fichier villes.csv suivant :
nom,population,departement,altitudeLyon,522250,69,175Marseille,870018,13,12Lille,236234,59,27Toulouse,493465,31,141Bordeaux,257804,33,6a. Combien d'enregistrements contient cette table ? Combien d'attributs ?
b. Écrire un programme Python qui lit ce fichier et stocke les données dans un tableau de dictionnaires, en convertissant population et altitude en entiers.
c. Afficher le nom et la population de chaque ville.
Solution
a. 5 enregistrements (lignes de données) et 4 attributs (colonnes : nom, population, departement, altitude).
b.
import csv
table = []with open("villes.csv", "r", encoding="utf-8") as fichier: lecteur = csv.DictReader(fichier) for ligne in lecteur: enregistrement = dict(ligne) enregistrement["population"] = int(enregistrement["population"]) enregistrement["altitude"] = int(enregistrement["altitude"]) table.append(enregistrement)c.
for ville in table: print(f"{ville['nom']} : {ville['population']} habitants")Exercice 2 - Écriture d'un fichier CSV
Section intitulée « Exercice 2 - Écriture d'un fichier CSV »On dispose du tableau suivant :
films = [ {"titre": "Le Fabuleux Destin d'Amélie Poulain", "annee": 2001, "realisateur": "Jean-Pierre Jeunet"}, {"titre": "Intouchables", "annee": 2011, "realisateur": "Olivier Nakache"}, {"titre": "La Haine", "annee": 1995, "realisateur": "Mathieu Kassovitz"}]a. Écrire un programme qui enregistre ces données dans un fichier films.csv.
b. Ouvrir le fichier produit avec un éditeur de texte et vérifier son contenu.
Solution
a.
import csv
films = [ {"titre": "Le Fabuleux Destin d'Amélie Poulain", "annee": 2001, "realisateur": "Jean-Pierre Jeunet"}, {"titre": "Intouchables", "annee": 2011, "realisateur": "Olivier Nakache"}, {"titre": "La Haine", "annee": 1995, "realisateur": "Mathieu Kassovitz"}]
with open("films.csv", "w", encoding="utf-8", newline="") as fichier: colonnes = ["titre", "annee", "realisateur"] ecrivain = csv.DictWriter(fichier, fieldnames=colonnes) ecrivain.writeheader() for film in films: ecrivain.writerow(film)b. Le fichier contient :
titre,annee,realisateurLe Fabuleux Destin d'Amélie Poulain,2001,Jean-Pierre JeunetIntouchables,2011,Olivier NakacheLa Haine,1995,Mathieu KassovitzRecherche et filtrage
Section intitulée « Recherche et filtrage »Exercice 3 - Sélection de lignes
Section intitulée « Exercice 3 - Sélection de lignes »On travaille avec la table des villes de l'exercice 1.
a. Écrire une instruction qui renvoie la liste des villes de plus de 300 000 habitants.
b. Écrire une instruction qui renvoie la liste des villes dont l'altitude est inférieure à 50 mètres.
c. Écrire une instruction qui renvoie la liste des villes du département 13 ou 69.
Solution
a.
grandes = [v for v in table if v["population"] > 300000]for v in grandes: print(v["nom"]) # Lyon, Marseille, Toulouseb.
basses = [v for v in table if v["altitude"] < 50]for v in basses: print(f"{v['nom']} ({v['altitude']} m)")# Marseille (12 m), Lille (27 m), Bordeaux (6 m)c.
selection = [v for v in table if v["departement"] in ["13", "69"]]for v in selection: print(v["nom"]) # Lyon, MarseilleExercice 4 - Projection et agrégation
Section intitulée « Exercice 4 - Projection et agrégation »a. À partir de la table des villes, créer un nouveau tableau ne contenant que les attributs nom et population.
b. Calculer la population totale des 5 villes.
c. Calculer l'altitude moyenne.
d. Trouver la ville la plus peuplée et la moins peuplée.
Solution
a.
extrait = [{"nom": v["nom"], "population": v["population"]} for v in table]b.
total = sum(v["population"] for v in table)print(f"Population totale : {total}") # 2 379 771c.
altitudes = [v["altitude"] for v in table]moyenne = sum(altitudes) / len(altitudes)print(f"Altitude moyenne : {moyenne} m") # 72.2 md.
plus_peuplee = max(table, key=lambda v: v["population"])moins_peuplee = min(table, key=lambda v: v["population"])print(f"Plus peuplée : {plus_peuplee['nom']}") # Marseilleprint(f"Moins peuplée : {moins_peuplee['nom']}") # LilleExercice 5 - Tri d'une table
Section intitulée « Exercice 5 - Tri d'une table »a. Trier la table des villes par population croissante. Afficher le résultat.
b. Trier par nom alphabétique.
c. Trier par altitude décroissante.
d. On ajoute des villes ayant la même altitude. Le tri est-il stable ? Vérifier.
Solution
a.
par_pop = sorted(table, key=lambda v: v["population"])for v in par_pop: print(f"{v['nom']} : {v['population']}")# Lille, Toulouse, Bordeaux, Lyon, Marseilleb.
par_nom = sorted(table, key=lambda v: v["nom"])for v in par_nom: print(v["nom"])# Bordeaux, Lille, Lyon, Marseille, Toulousec.
par_alt_desc = sorted(table, key=lambda v: v["altitude"], reverse=True)for v in par_alt_desc: print(f"{v['nom']} ({v['altitude']} m)")# Lyon (175), Toulouse (141), Lille (27), Marseille (12), Bordeaux (6)d. Oui, le tri de Python (Timsort) est stable : si deux villes ont la même altitude, elles restent dans leur ordre d'apparition d'origine.
Exercice 6 - Doublons et cohérence
Section intitulée « Exercice 6 - Doublons et cohérence »On dispose de la table suivante :
notes = [ {"nom": "Dupont", "matiere": "NSI", "note": 15}, {"nom": "Martin", "matiere": "NSI", "note": 12}, {"nom": "Dupont", "matiere": "Maths", "note": 14}, {"nom": "Durand", "matiere": "NSI", "note": "18"}, {"nom": "Martin", "matiere": "NSI", "note": 16}, {"nom": "Petit", "matiere": "NSI", "note": -2}]a. Identifier les doublons sur l'attribut nom dans la matière NSI.
b. Repérer les problèmes de cohérence dans cette table (types, valeurs aberrantes).
c. Écrire une fonction qui nettoie la table : convertir les notes en entiers et supprimer les notes hors de [0, 20].
Solution
a. En filtrant sur la matière NSI :
- Dupont n'apparait qu'une fois en NSI (l'autre est en Maths).
- Martin apparait deux fois en NSI (notes 12 et 16) : c'est un doublon.
b. Problèmes :
- Ligne 3 (Durand) : la note
"18"est une chaîne au lieu d'un entier. - Ligne 5 (Petit) : la note
-2est aberrante (hors de [0, 20]).
c.
def nettoyer_notes(table): resultat = [] for ligne in table: copie = dict(ligne) try: copie["note"] = int(copie["note"]) except (ValueError, TypeError): continue if 0 <= copie["note"] <= 20: resultat.append(copie) return resultat
propre = nettoyer_notes(notes)for n in propre: print(n)Fusion de tables
Section intitulée « Fusion de tables »Exercice 7 - Jointure simple
Section intitulée « Exercice 7 - Jointure simple »On dispose de deux tables :
commandes = [ {"id_commande": 1, "id_client": 10, "produit": "Livre", "prix": 15}, {"id_commande": 2, "id_client": 20, "produit": "Stylo", "prix": 3}, {"id_commande": 3, "id_client": 10, "produit": "Cahier", "prix": 5}, {"id_commande": 4, "id_client": 30, "produit": "Gomme", "prix": 2}]
clients = [ {"id_client": 10, "nom": "Dupont", "ville": "Lyon"}, {"id_client": 20, "nom": "Martin", "ville": "Paris"}, {"id_client": 30, "nom": "Durand", "ville": "Lille"}]a. Quelle est la clé de jointure ? Identifier la clé primaire et la clé étrangère.
b. Effectuer la jointure et afficher, pour chaque commande, le nom du client, le produit et le prix.
c. Après la jointure, filtrer les commandes des clients de Lyon.
Solution
a. La clé de jointure est "id_client". C'est la clé primaire de la table clients et la clé étrangère de la table commandes.
b.
def jointure(table1, table2, cle): resultat = [] for l1 in table1: for l2 in table2: if l1[cle] == l2[cle]: fusion = {} fusion.update(l1) fusion.update(l2) resultat.append(fusion) return resultat
complet = jointure(commandes, clients, "id_client")for c in complet: print(f"{c['nom']} a commandé {c['produit']} ({c['prix']} euros)")# Dupont a commandé Livre (15 euros)# Martin a commandé Stylo (3 euros)# Dupont a commandé Cahier (5 euros)# Durand a commandé Gomme (2 euros)c.
lyon = [c for c in complet if c["ville"] == "Lyon"]for c in lyon: print(f"{c['produit']} - {c['prix']} euros")# Livre - 15 euros# Cahier - 5 eurosExercice 8 - Jointure avec données manquantes
Section intitulée « Exercice 8 - Jointure avec données manquantes »On ajoute un client sans commande et une commande avec un client inconnu :
clients.append({"id_client": 40, "nom": "Morel", "ville": "Bordeaux"})commandes.append({"id_commande": 5, "id_client": 99, "produit": "Règle", "prix": 4})a. Effectuer la jointure. Morel et la commande 5 apparaissent-ils dans le résultat ?
b. Expliquer pourquoi.
Solution
a. Non, ni Morel ni la commande 5 n'apparaissent dans le résultat.
b. La jointure ne conserve que les lignes ayant une correspondance dans les deux tables :
- Morel (id_client = 40) n'a aucune commande → pas de correspondance dans
commandes. - La commande 5 (id_client = 99) n'a aucun client correspondant → pas de correspondance dans
clients.
Exercice 9 - Calculs après jointure
Section intitulée « Exercice 9 - Calculs après jointure »On reprend les tables commandes et clients de l'exercice 7.
a. Après jointure, calculer le montant total des commandes par client.
b. Trouver le client qui a dépensé le plus.
c. Calculer le montant total de toutes les commandes.
Solution
a.
complet = jointure(commandes, clients, "id_client")
totaux = {}for c in complet: nom = c["nom"] if nom in totaux: totaux[nom] += c["prix"] else: totaux[nom] = c["prix"]
for nom, total in totaux.items(): print(f"{nom} : {total} euros")# Dupont : 20 euros# Martin : 3 euros# Durand : 2 eurosb.
meilleur_client = max(totaux, key=lambda n: totaux[n])print(f"Meilleur client : {meilleur_client} ({totaux[meilleur_client]} euros)")# Meilleur client : Dupont (20 euros)c.
total_general = sum(c["prix"] for c in complet)print(f"Total : {total_general} euros") # 25 eurosExercice 10 - Questions transversales
Section intitulée « Exercice 10 - Questions transversales »On dispose de la table suivante (déjà en mémoire) :
pays = [ {"nom": "France", "capitale": "Paris", "population": 67, "continent": "Europe"}, {"nom": "Japon", "capitale": "Tokyo", "population": 126, "continent": "Asie"}, {"nom": "Brésil", "capitale": "Brasilia", "population": 213, "continent": "Amérique"}, {"nom": "Allemagne", "capitale": "Berlin", "population": 83, "continent": "Europe"}, {"nom": "Inde", "capitale": "New Delhi", "population": 1408, "continent": "Asie"}, {"nom": "Canada", "capitale": "Ottawa", "population": 38, "continent": "Amérique"}, {"nom": "Italie", "capitale": "Rome", "population": 60, "continent": "Europe"}]Les populations sont en millions.
a. Filtrer les pays d'Europe. Combien sont-ils ?
b. Trier tous les pays par population décroissante.
c. Calculer la population totale par continent.
d. Trouver le pays le plus peuplé de chaque continent.
Solution
a.
europe = [p for p in pays if p["continent"] == "Europe"]print(f"Pays d'Europe : {len(europe)}") # 3for p in europe: print(p["nom"]) # France, Allemagne, Italieb.
par_pop = sorted(pays, key=lambda p: p["population"], reverse=True)for p in par_pop: print(f"{p['nom']} : {p['population']} M")# Inde, Brésil, Japon, Allemagne, France, Italie, Canadac.
pop_continent = {}for p in pays: c = p["continent"] if c in pop_continent: pop_continent[c] += p["population"] else: pop_continent[c] = p["population"]
for c, pop in pop_continent.items(): print(f"{c} : {pop} M")# Europe : 210 M# Asie : 1534 M# Amérique : 251 Md.
continents = set(p["continent"] for p in pays)for c in continents: pays_du_continent = [p for p in pays if p["continent"] == c] plus_peuple = max(pays_du_continent, key=lambda p: p["population"]) print(f"{c} : {plus_peuple['nom']} ({plus_peuple['population']} M)")# Europe : Allemagne (83 M)# Asie : Inde (1408 M)# Amérique : Brésil (213 M)Activités
Section intitulée « Activités »Activité 1 - Explorer un jeu de données réel (open data)
Section intitulée « Activité 1 - Explorer un jeu de données réel (open data) »Créer le fichier communes.csv suivant (extrait simplifié) :
nom,code_postal,population,superficie,regionParis,75000,2161000,105,Ile-de-FranceMarseille,13000,870731,241,Provence-Alpes-Cote d'AzurLyon,69000,522969,48,Auvergne-Rhone-AlpesToulouse,31000,493465,118,OccitanieNice,06000,342669,72,Provence-Alpes-Cote d'AzurNantes,44000,318808,65,Pays de la LoireMontpellier,34000,290053,57,OccitanieStrasbourg,67000,287228,78,Grand EstBordeaux,33000,257804,50,Nouvelle-AquitaineLille,59000,236234,35,Hauts-de-FranceQuestions
Section intitulée « Questions »a. Importer les données et convertir les types numériques.
b. Calculer la densité de population (habitants par km²) pour chaque commune et l'ajouter comme nouvel attribut.
c. Afficher les 5 communes les plus denses, triées par densité décroissante.
d. Calculer la population totale et la population moyenne des communes du fichier.
e. Regrouper les communes par région et calculer la population totale de chaque région.
f. Exporter les résultats (avec la densité) dans un nouveau fichier communes_enrichi.csv.
Correction
a.
import csv
table = []with open("communes.csv", "r", encoding="utf-8") as f: lecteur = csv.DictReader(f) for ligne in lecteur: e = dict(ligne) e["population"] = int(e["population"]) e["superficie"] = int(e["superficie"]) table.append(e)b.
for commune in table: commune["densite"] = round(commune["population"] / commune["superficie"])c.
par_densite = sorted(table, key=lambda c: c["densite"], reverse=True)print("Top 5 des communes les plus denses :")for c in par_densite[:5]: print(f" {c['nom']} : {c['densite']} hab/km2")# Paris : 20581, Lyon : 10895, Lille : 6749, Montpellier : 5088, Nantes : 4905d.
pop_totale = sum(c["population"] for c in table)pop_moyenne = pop_totale / len(table)print(f"Population totale : {pop_totale}") # 5 780 961print(f"Population moyenne : {pop_moyenne:.0f}") # 578 096e.
par_region = {}for c in table: r = c["region"] if r in par_region: par_region[r] += c["population"] else: par_region[r] = c["population"]
for region, pop in sorted(par_region.items(), key=lambda x: x[1], reverse=True): print(f" {region} : {pop}")f.
with open("communes_enrichi.csv", "w", encoding="utf-8", newline="") as f: colonnes = ["nom", "code_postal", "population", "superficie", "region", "densite"] ecrivain = csv.DictWriter(f, fieldnames=colonnes) ecrivain.writeheader() for c in table: ecrivain.writerow(c)Activité 2 - Le bulletin de notes (fusion de tables)
Section intitulée « Activité 2 - Le bulletin de notes (fusion de tables) »Créer les trois fichiers suivants :
eleves.csv :
id_eleve,nom,prenom,classe1,Dupont,Marie,1NSI-A2,Martin,Léo,1NSI-A3,Durand,Emma,1NSI-B4,Petit,Hugo,1NSI-B5,Leroy,Alice,1NSI-Anotes.csv :
id_eleve,matiere,note1,NSI,151,Maths,141,Anglais,122,NSI,182,Maths,102,Anglais,163,NSI,123,Maths,173,Anglais,144,NSI,84,Maths,94,Anglais,115,NSI,165,Maths,155,Anglais,17matieres.csv :
matiere,coefficientNSI,4Maths,4Anglais,3Questions
Section intitulée « Questions »a. Importer les trois fichiers.
b. Fusionner notes et eleves sur id_eleve, puis fusionner le résultat avec matieres sur matiere.
c. Calculer la moyenne pondérée de chaque élève.
d. Afficher le bulletin complet sous forme de tableau lisible.
e. Déterminer le premier et le dernier de la classe (par moyenne pondérée).
Correction
import csv
def charger_csv(nom_fichier): table = [] with open(nom_fichier, "r", encoding="utf-8") as f: for ligne in csv.DictReader(f): table.append(dict(ligne)) return table
def jointure(t1, t2, cle): resultat = [] for l1 in t1: for l2 in t2: if l1[cle] == l2[cle]: fusion = {} fusion.update(l1) fusion.update(l2) resultat.append(fusion) return resultat
# a. Importereleves = charger_csv("eleves.csv")notes = charger_csv("notes.csv")matieres = charger_csv("matieres.csv")
# Conversionsfor n in notes: n["id_eleve"] = int(n["id_eleve"]) n["note"] = float(n["note"])for e in eleves: e["id_eleve"] = int(e["id_eleve"])for m in matieres: m["coefficient"] = int(m["coefficient"])
# b. Fusionsetape1 = jointure(notes, eleves, "id_eleve")complet = jointure(etape1, matieres, "matiere")
# c. Moyenne pondérée par élèvemoyennes = {}for ligne in complet: nom = f"{ligne['prenom']} {ligne['nom']}" if nom not in moyennes: moyennes[nom] = {"somme_ponderee": 0, "somme_coefs": 0} moyennes[nom]["somme_ponderee"] += ligne["note"] * ligne["coefficient"] moyennes[nom]["somme_coefs"] += ligne["coefficient"]
# d. Affichageprint(f"{'Élève':<20} {'Moyenne':>8}")print("-" * 30)for nom, data in moyennes.items(): moy = data["somme_ponderee"] / data["somme_coefs"] print(f"{nom:<20} {moy:>8.2f}")
# e. Premier et dernierclassement = sorted(moyennes.items(), key=lambda x: x[1]["somme_ponderee"] / x[1]["somme_coefs"], reverse=True)premier = classement[0]dernier = classement[-1]moy_p = premier[1]["somme_ponderee"] / premier[1]["somme_coefs"]moy_d = dernier[1]["somme_ponderee"] / dernier[1]["somme_coefs"]print(f"\nPremier : {premier[0]} ({moy_p:.2f})")print(f"Dernier : {dernier[0]} ({moy_d:.2f})")Activité 3 - Détective de données (cohérence et nettoyage)
Section intitulée « Activité 3 - Détective de données (cohérence et nettoyage) »Créer le fichier inscriptions.csv suivant (volontairement plein d'erreurs) :
nom,prenom,age,email,classeDupont,Marie,16,[email protected],1NSI-AMartin,Léo,17,[email protected],1NSI-ADurand,Emma,seize,[email protected],1NSI-B,Hugo,15,[email protected],1NSI-BPetit,Hugo,15,[email protected],1NSI-BMartin,Léo,17,[email protected],1NSI-ALeroy,Alice,-3,[email protected],1NSI-ABernard,Tom,16,,1NSI-BQuestions
Section intitulée « Questions »a. Importer le fichier. Combien de lignes contient-il ?
b. Identifier tous les problèmes :
- Valeurs manquantes (nom vide, email vide)
- Types incorrects (age = "seize")
- Valeurs aberrantes (age = -3)
- Doublons (lignes identiques)
c. Écrire une fonction nettoyer(table) qui :
- Supprime les doublons exacts
- Signale les lignes avec des valeurs manquantes
- Signale les lignes avec un age non numérique ou hors [10, 20]
d. Exporter la table nettoyée dans inscriptions_propres.csv.
Correction
import csv
# a. Importtable = []with open("inscriptions.csv", "r", encoding="utf-8") as f: for ligne in csv.DictReader(f): table.append(dict(ligne))print(f"Nombre de lignes : {len(table)}") # 8
# b. Identification des problèmesprint("\n--- Analyse ---")for i, ligne in enumerate(table): problemes = [] # Valeurs manquantes for cle, val in ligne.items(): if val.strip() == "": problemes.append(f"{cle} manquant") # Type de age try: age = int(ligne["age"]) if age < 10 or age > 20: problemes.append(f"age aberrant ({age})") except ValueError: problemes.append(f"age non numerique ('{ligne['age']}')") if problemes: print(f"Ligne {i} ({ligne.get('nom', '?')}) : {', '.join(problemes)}")
# Doublonsfor i in range(len(table)): for j in range(i + 1, len(table)): if table[i] == table[j]: print(f"Doublon : lignes {i} et {j}")
# c. Nettoyagedef nettoyer(table): propre = [] vus = [] for ligne in table: # Suppression des doublons cle_unique = (ligne["nom"], ligne["prenom"], ligne["email"]) if cle_unique in vus: continue vus.append(cle_unique) # Valeurs manquantes if any(v.strip() == "" for v in ligne.values()): print(f" Ignoree (valeur manquante) : {ligne}") continue # Conversion et validation de l'age try: ligne["age"] = int(ligne["age"]) except ValueError: print(f" Ignoree (age invalide) : {ligne}") continue if ligne["age"] < 10 or ligne["age"] > 20: print(f" Ignoree (age aberrant) : {ligne}") continue propre.append(ligne) return propre
print("\n--- Nettoyage ---")propre = nettoyer(table)print(f"\nLignes conservees : {len(propre)}")
# d. Exportwith open("inscriptions_propres.csv", "w", encoding="utf-8", newline="") as f: colonnes = ["nom", "prenom", "age", "email", "classe"] ecrivain = csv.DictWriter(f, fieldnames=colonnes) ecrivain.writeheader() for ligne in propre: ecrivain.writerow(ligne)Projet final - Analyse d'un championnat sportif
Section intitulée « Projet final - Analyse d'un championnat sportif »Partie A - Créer les données
Section intitulée « Partie A - Créer les données »a. Créer un fichier equipes.csv contenant 6 équipes avec les colonnes : id_equipe, nom, ville, stade.
b. Créer un fichier matchs.csv contenant 10 matchs avec les colonnes : id_match, id_equipe_dom, id_equipe_ext, buts_dom, buts_ext.
Partie B - Importation et fusion
Section intitulée « Partie B - Importation et fusion »c. Importer les deux fichiers.
d. Fusionner pour afficher, pour chaque match, les noms des équipes et le score (au lieu des identifiants).
Partie C - Classement
Section intitulée « Partie C - Classement »e. Calculer pour chaque équipe : nombre de matchs joués, victoires, nuls, défaites, buts marqués, buts encaissés, différence de buts, points (3 pour une victoire, 1 pour un nul, 0 pour une défaite).
f. Afficher le classement trié par points décroissants (puis par différence de buts en cas d'égalité).
Partie D - Statistiques
Section intitulée « Partie D - Statistiques »g. Calculer le nombre total de buts marqués dans le championnat.
h. Trouver le match avec le plus de buts et la plus grosse victoire.
i. Exporter le classement final dans un fichier classement.csv.
Correction
import csv
# Exemple de donnéesequipes = [ {"id_equipe": 1, "nom": "Lyon", "ville": "Lyon", "stade": "Groupama"}, {"id_equipe": 2, "nom": "Marseille", "ville": "Marseille", "stade": "Velodrome"}, {"id_equipe": 3, "nom": "Paris", "ville": "Paris", "stade": "Parc des Princes"}, {"id_equipe": 4, "nom": "Lille", "ville": "Lille", "stade": "Pierre Mauroy"}, {"id_equipe": 5, "nom": "Nantes", "ville": "Nantes", "stade": "Beaujoire"}, {"id_equipe": 6, "nom": "Toulouse", "ville": "Toulouse", "stade": "Stadium"}]
matchs = [ {"id_match": 1, "id_dom": 1, "id_ext": 2, "buts_dom": 2, "buts_ext": 1}, {"id_match": 2, "id_dom": 3, "id_ext": 4, "buts_dom": 3, "buts_ext": 0}, {"id_match": 3, "id_dom": 5, "id_ext": 6, "buts_dom": 1, "buts_ext": 1}, {"id_match": 4, "id_dom": 2, "id_ext": 3, "buts_dom": 0, "buts_ext": 2}, {"id_match": 5, "id_dom": 4, "id_ext": 1, "buts_dom": 1, "buts_ext": 3}, {"id_match": 6, "id_dom": 6, "id_ext": 5, "buts_dom": 2, "buts_ext": 0}, {"id_match": 7, "id_dom": 1, "id_ext": 3, "buts_dom": 1, "buts_ext": 1}, {"id_match": 8, "id_dom": 2, "id_ext": 4, "buts_dom": 2, "buts_ext": 2}, {"id_match": 9, "id_dom": 5, "id_ext": 1, "buts_dom": 0, "buts_ext": 1}, {"id_match": 10, "id_dom": 6, "id_ext": 3, "buts_dom": 1, "buts_ext": 4}]
# Dictionnaire id -> nom pour accès rapidenoms = {e["id_equipe"]: e["nom"] for e in equipes}
# Classementstats = {}for e in equipes: stats[e["id_equipe"]] = { "nom": e["nom"], "mj": 0, "v": 0, "n": 0, "d": 0, "bp": 0, "bc": 0, "diff": 0, "pts": 0 }
for m in matchs: dom = m["id_dom"] ext = m["id_ext"] bd = m["buts_dom"] be = m["buts_ext"]
stats[dom]["mj"] += 1 stats[ext]["mj"] += 1 stats[dom]["bp"] += bd stats[dom]["bc"] += be stats[ext]["bp"] += be stats[ext]["bc"] += bd
if bd > be: stats[dom]["v"] += 1 stats[dom]["pts"] += 3 stats[ext]["d"] += 1 elif bd < be: stats[ext]["v"] += 1 stats[ext]["pts"] += 3 stats[dom]["d"] += 1 else: stats[dom]["n"] += 1 stats[ext]["n"] += 1 stats[dom]["pts"] += 1 stats[ext]["pts"] += 1
for s in stats.values(): s["diff"] = s["bp"] - s["bc"]
# Affichage du classementclassement = sorted(stats.values(), key=lambda s: (s["pts"], s["diff"]), reverse=True)
print(f"{'Pos':<4} {'Equipe':<12} {'MJ':<4} {'V':<4} {'N':<4} {'D':<4} " f"{'BP':<4} {'BC':<4} {'Diff':<5} {'Pts':<4}")print("-" * 55)for i, s in enumerate(classement): diff = f"+{s['diff']}" if s['diff'] > 0 else str(s['diff']) print(f"{i+1:<4} {s['nom']:<12} {s['mj']:<4} {s['v']:<4} {s['n']:<4} " f"{s['d']:<4} {s['bp']:<4} {s['bc']:<4} {diff:<5} {s['pts']:<4}")
# Statistiquestotal_buts = sum(m["buts_dom"] + m["buts_ext"] for m in matchs)print(f"\nTotal buts : {total_buts}")
plus_de_buts = max(matchs, key=lambda m: m["buts_dom"] + m["buts_ext"])print(f"Match avec le plus de buts : {noms[plus_de_buts['id_dom']]} " f"{plus_de_buts['buts_dom']}-{plus_de_buts['buts_ext']} " f"{noms[plus_de_buts['id_ext']]}")© 2026 Corentin Dupont - LyCode
Créé avec Astro Starlight