Python (école d'ingénieur) · Chapitre 7 · Exercice
Application complète : analyse de données météo
Fichiers, exceptions et modules
Énoncé
Créer une application modulaire et robuste qui :
- Lit un fichier CSV de données météo (contenant les colonnes :
date,tmin,tmax,precipitation).
- Calcule des statistiques mensuelles (températures moyennes et extrêmes absolues, précipitations cumulées).
- Génère un rapport texte.
- Sauvegarde les résultats mensuels dans un nouveau fichier CSV.
- Gère les erreurs de conversion et de lecture.
Corrigé
import csv
from datetime import datetime
from collections import defaultdict
class AnalyseMeteo:
"""Classe pour l'analyse de données météo."""
def __init__(self, nom_fichier):
self.nom_fichier = nom_fichier
self.donnees = []
self.statistiques = {}
def charger_donnees(self):
"""Charge les données météo depuis un fichier CSV."""
try:
with open(self.nom_fichier, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for ligne in reader:
try:
date = datetime.strptime(ligne['date'], '%Y-%m-%d')
tmin = float(ligne['tmin'])
tmax = float(ligne['tmax'])
precip = float(ligne['precipitation'])
self.donnees.append({
'date': date,
'tmin': tmin,
'tmax': tmax,
'tavg': (tmin + tmax) / 2,
'precip': precip
})
except (ValueError, KeyError) as e:
print(f"Ligne ignorée (erreur de conversion) : {ligne}")
continue
print(f"Chargement terminé : {len(self.donnees)} enregistrements.")
return True
except FileNotFoundError:
print(f"Erreur : Fichier {self.nom_fichier} introuvable.")
return False
def calculer_statistiques(self):
"""Calcule les statistiques mensuelles."""
if not self.donnees:
print("Aucune donnée à analyser.")
return
# Regroupement par mois
mois_stats = defaultdict(lambda: {
'tmin_sum': 0.0, 'tmax_sum': 0.0, 'tavg_sum': 0.0, 'precip_sum': 0.0,
'count': 0, 'tmin_min': float('inf'), 'tmax_max': float('-inf')
})
for d in self.donnees:
mois_cle = d['date'].strftime('%Y-%m') # Format "2024-01"
stats = mois_stats[mois_cle]
stats['tmin_sum'] += d['tmin']
stats['tmax_sum'] += d['tmax']
stats['tavg_sum'] += d['tavg']
stats['precip_sum'] += d['precip']
stats['count'] += 1
stats['tmin_min'] = min(stats['tmin_min'], d['tmin'])
stats['tmax_max'] = max(stats['tmax_max'], d['tmax'])
# Calcul des moyennes
self.statistiques = {}
for mois, stats in mois_stats.items():
cnt = stats['count']
self.statistiques[mois] = {
'tmin_moy': stats['tmin_sum'] / cnt,
'tmax_moy': stats['tmax_sum'] / cnt,
'tavg_moy': stats['tavg_sum'] / cnt,
'tmin_min': stats['tmin_min'],
'tmax_max': stats['tmax_max'],
'precip_tot': stats['precip_sum'],
'nb_jours': cnt
}
# Identification des extrêmes absolus
mois_tmin_min = min(self.statistiques.items(), key=lambda x: x[1]['tmin_min'])
mois_tmax_max = max(self.statistiques.items(), key=lambda x: x[1]['tmax_max'])
self.statistiques['_extrema'] = {
'mois_plus_froid': mois_tmin_min[0],
'temp_min_absolue': mois_tmin_min[1]['tmin_min'],
'mois_plus_chaud': mois_tmax_max[0],
'temp_max_absolue': mois_tmax_max[1]['tmax_max']
}
def generer_rapport(self, fichier_rapport="rapport_meteo.txt"):
"""Génère un rapport texte des statistiques."""
if not self.statistiques:
print("Calculez d'abord les statistiques.")
return
with open(fichier_rapport, 'w', encoding='utf-8') as f:
f.write("=" * 60 + "\n")
f.write("RAPPORT D'ANALYSE MÉTÉO\n")
f.write("=" * 60 + "\n\n")
ext = self.statistiques['_extrema']
f.write("EXTREMES :\n")
f.write(f" Mois le plus froid : {ext['mois_plus_froid']}")
f.write(f" (temp. min: {ext['temp_min_absolue']:.1f}°C)\n")
f.write(f" Mois le plus chaud : {ext['mois_plus_chaud']}")
f.write(f" (temp. max: {ext['temp_max_absolue']:.1f}°C)\n\n")
f.write("STATISTIQUES MENSUELLES :\n")
f.write("-" * 60 + "\n")
f.write(f"{'Mois':10} {'Tmin':8} {'Tmax':8} {'Tavg':8} {'Précip':10}\n")
f.write("-" * 60 + "\n")
for mois in sorted(self.statistiques.keys()):
if mois == '_extrema':
continue
s = self.statistiques[mois]
f.write(f"{mois:10} {s['tmin_moy']:8.1f} {s['tmax_moy']:8.1f} ")
f.write(f"{s['tavg_moy']:8.1f} {s['precip_tot']:10.1f}\n")
print(f"Rapport généré : {fichier_rapport}")
def exporter_csv(self, fichier_sortie="statistiques_mensuelles.csv"):
"""Exporte les statistiques mensuelles vers un fichier CSV."""
if not self.statistiques:
print("Calculez d'abord les statistiques.")
return
with open(fichier_sortie, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['Mois', 'Tmin_moy', 'Tmax_moy', 'Tavg_moy',
'Tmin_min', 'Tmax_max', 'Precip_tot', 'Nb_jours'])
for mois in sorted(self.statistiques.keys()):
if mois == '_extrema':
continue
s = self.statistiques[mois]
writer.writerow([
mois, f"{s['tmin_moy']:.1f}", f"{s['tmax_moy']:.1f}",
f"{s['tavg_moy']:.1f}", f"{s['tmin_min']:.1f}",
f"{s['tmax_max']:.1f}", f"{s['precip_tot']:.1f}", s['nb_jours']
])
print(f"Export CSV : {fichier_sortie}")
# Création d'un fichier CSV de test
def creer_fichier_test():
with open("meteo_test.csv", "w", encoding="utf-8") as f:
f.write("date,tmin,tmax,precipitation\n")
f.write("2024-01-15,2.0,8.0,12.5\n")
f.write("2024-01-20,1.5,7.5,8.0\n")
f.write("2024-02-10,3.0,10.0,5.0\n")
f.write("2024-02-15,4.0,12.0,0.0\n")
# Exemple d'utilisation
if __name__ == "__main__":
creer_fichier_test()
analyse = AnalyseMeteo("meteo_test.csv")
if analyse.charger_donnees():
analyse.calculer_statistiques()
analyse.generer_rapport()
analyse.exporter_csv()100 % gratuit
La suite du chapitre est sur Adloun
- 5 autres exercices corrigés dans ce chapitre, et 7 à chercher avec le tuteur
- Les 2 QCM du chapitre, le premier sans compte
- Le tuteur, qui guide pas à pas sans donner la réponse
Sans compte : le cours et le premier QCM. Exercices et tuteur : inscription gratuite en 30 secondes, sans carte bancaire.