Organiser des données sous forme de tableaux est très répandu.
Par exemple, le bulletin d'un élève est organisé en table et indique pour chaque matière, la moyenne de l'élève, la moyenne de la classe, l'appréciation du professeur. La liste de présence des élèves est également représentée sous forme d'une table indiquant pour chaque élève s'il est présent ou absent ce jour. L'utilisation de tables est très ancienne car on retrouve des tables de données dans les livres de comptes dans l'Egypte ancienne.
En informatique, les tables de données sont rapidement devenues le principal moyen de stocker des données. L'analyse de ces données est utilisée dans de nombreux domaines : calcul scientifique, intelligence artificielle, programmation Web, bio-informatique, informatique financière, etc. De nombreuses données en tables sont disponibles sur les sites de données ouvertes.
Voici un exemple de table avec des informations sur des élèves :
prénom | jour | mois | année | sexe | projet |
---|---|---|---|---|---|
Louan | 13 | 4 | 2003 | G | être heureux |
Mael | 29 | 3 | 2003 | G | manger une glace |
Alexis | 20 | 10 | 2003 | G | gagner au loto |
Théo | 25 | 4 | 2003 | G | avoir une bonne note au prochain devoir |
Arthur | 14 | 1 | 2003 | G | devenir quelqu’un de célèbre |
Tristan | 18 | 9 | 2003 | G | gagner le Tour de France |
Leo | 10 | 5 | 2003 | G | dormir plus longtemps le matin |
Valentin | 30 | 12 | 2003 | G | créer un jeu vidéo |
Elie | 19 | 2 | 2003 | G | devenir astronaute |
Jenifer | 30 | 3 | 2003 | F | marcher sur la lune |
Cette table peut être représenté par le fichier texte suivant :
prénom,jour,mois,année,sexe,projet
Louan,13,4,2003,G,être heureux
Mael,29,3,2003,G,manger une glace
Alexis,20,10,2003,G,gagner au loto
Théo,25,4,2003,G,avoir une bonne note au prochain devoir
Arthur,14,1,2003,G,devenir quelqu’un de célèbre
Tristan,18,9,2003,G,gagner le Tour de France
Leo,10,5,2003,G,dormir plus longtemps le matin
Valentin,30,12,2003,G,créer un jeu vidéo
Elie,19,2,2003,G,devenir astronaute
Jenifer,30,3,2003,F,marcher sur la lune
Pour travailler sur les données d'un tel fichier, il faudra commencer par charger les données. On pourra soit les charger dans un tableau de tableaux
[['prénom', 'jour', 'mois', 'année', 'sexe', 'projet'], ['Louan', '13', '4', '2003', 'G', 'être heureux'], ['Mael', '29', '3', '2003', 'G', 'manger une glace'], ['Alexis', '20', '10', '2003', 'G', 'gagner au loto'], ['Théo', '25', '4', '2003', 'G', 'avoir une bonne note au prochain devoir'], ['Arthur', '14', '1', '2003', 'G', 'devenir quelqu’un de célèbre'], ['Tristan', '18', '9', '2003', 'G', 'gagner le Tour de France'], ['Leo', '10', '5', '2003', 'G', 'dormir plus longtemps le matin'], ['Valentin', '30', '12', '2003', 'G', 'créer un jeu vidéo'], ['Elie', '19', '2', '2003', 'G', 'devenir astronaute'], ['Jenifer', '30', '3', '2003', 'F', 'marcher sur la lune']]
ou dans un tableau de dictionnaires :
[{'prénom': 'Louan', 'jour': '13', 'mois': '4', 'année': '2003', 'sexe': 'G', 'projet': 'être heureux'}, {'prénom': 'Mael', 'jour': '29', 'mois': '3', 'année': '2003', 'sexe': 'G', 'projet': 'manger une glace'}, {'prénom': 'Alexis', 'jour': '20', 'mois': '10', 'année': '2003', 'sexe': 'G', 'projet': 'gagner au loto'}, {'prénom': 'Théo', 'jour': '25', 'mois': '4', 'année': '2003', 'sexe': 'G', 'projet': 'avoir une bonne note au prochain devoir'}, {'prénom': 'Arthur', 'jour': '14', 'mois': '1', 'année': '2003', 'sexe': 'G', 'projet': 'devenir quelqu’un de célèbre'}, {'prénom': 'Tristan', 'jour': '18', 'mois': '9', 'année': '2003', 'sexe': 'G', 'projet': 'gagner le Tour de France'}, {'prénom': 'Leo', 'jour': '10', 'mois': '5', 'année': '2003', 'sexe': 'G', 'projet': 'dormir plus longtemps le matin'}, {'prénom': 'Valentin', 'jour': '30', 'mois': '12', 'année': '2003', 'sexe': 'G', 'projet': 'créer un jeu vidéo'}, {'prénom': 'Elie', 'jour': '19', 'mois': '2', 'année': '2003', 'sexe': 'G', 'projet': 'devenir astronaute'}, {'prénom': 'Jenifer', 'jour': '30', 'mois': '3', 'année': '2003', 'sexe': 'F', 'projet': 'marcher sur la lune'}]
Une fois les données chargées dans un tableau, on pourra travailler sur ces données : rechercher le nombre d'élèves nés en 2003, les élèves nés en avril, calculer le pourcentage de filles dans la classe, trier la table du plus jeune au plus vieux des élèves, etc.
Ne tardons plus, voici comment on peut procéder.
Pour charger les données d'une table il faudra lire le fichier contenant ces données pour les importer dans Python et les charger dans une variable. Une fois que la table sera importée dans une variable, il faudra mémoriser le contenu de la table dans un tableau (de tableaux ou de dictionnaires).
Un fichier TXT
tabulé est un simple fichier texte dans lequel :
Un fichier CSV
(pour l'anglais comma-separated values, soit "données séparées par des virgules") est un fichier texte dans lequel :
Exemple :
prénom,jour,mois,année,sexe,projet Louan,13,4,2003,G,être heureux Mael,29,3,2003,G,manger une glace Alexis,20,10,2003,G,gagner au loto Théo,25,4,2003,G,avoir une bonne note au prochain devoir Arthur,14,1,2003,G,devenir quelqu’un de célèbre Tristan,18,9,2003,G,gagner le Tour de France Leo,10,5,2003,G,dormir plus longtemps le matin Valentin,30,12,2003,G,créer un jeu vidéo Elie,19,2,2003,G,devenir astronaute Jenifer,30,3,2003,F,marcher sur la lune
Dans ce fichier
CSV
chaque ligne représente un élément de la table (ici un élève). La première ligne contient le nom des attributs ( = le nom de chaque champ) des éléments. Il y a donc en tout 6 attributs dans ce fichier CSV.
Pour les données tabulées l'usage est d'utiliser le format CSV
, et c'est ce que nous allons faire par la suite.
Remarque : Un autre format de données en tables est le format JSON
qui est plus élaboré. Il n'est pas explicitement au programme et vous en aurez juste un petit aperçu en fin de Notebook pour les plus curieux.
Remarque : le format CSV est le plus répandu des formats tabulés mais on rencontre souvent des variantes dans lesquelles le caractère de séparation est le point-virgule (";"), le deux-points (":") ou la barre verticale ("|"). En France, on utilise souvent le point-virgule comme caractère de séparation car la virgule est utilisée pour l'écriture des nombres décimaux ce qui peut poser des problèmes.
Avant de lire le fichier "eleves.csv" il faut d'abord l'ouvrir dans Python en utilisant la fonction read
.
fichier = open('eleves.csv', 'r', encoding = 'UTF-8') # on charge le contenu dans la variable 'fichier'
On a utilisé le paramètre 'r'
pour indiquer une ouverture en mode lecture ( read en anglais).
Remarque : On pourrait ensuite lire le contenu du fichier sous forme d'une unique chaîne de caractères en utilisant la fonction
read
fichier = open('eleves.csv', 'r', encoding = 'UTF-8') texte = fichier.read() # on lit le contenu sous la forme d'une unique chaine de caractères print(texte) # on affiche la chaine de caractères 'texte'mais ce n'est pas ainsi que l'on procèdera car il faudrait encore travailler sur cette chaîne pour mémoriser les données dans un tableau et cela peut se révéler fastidieux.
Pour lire un fichier CSV (ou TXT tabulé), la biliothèque standard de Python contient un module csv
qui contient des fonctions très pratiques pour lire et écrire des fichiers CSV. La mémorisation dans un tableau devenant alors très rapide. Voici comment on procède.
import csv
fichier = open('eleves.csv', 'r', encoding = 'UTF-8')
t = csv.reader(fichier, delimiter=',')
eleves = [] # on va mémoriser les données dans le tableau 'eleves'
for ligne in t:
eleves.append(ligne)
print(eleves) # pour afficher le contenu du tableau 'table'
Explications : Après avoir importé le module csv
, on ouvre le fichier "eleves.csv". La fonction reader
du module csv
prend en argument un fichier ouvert et renvoie une valeur spéciale représentant le fichier CSV. On parcourt ensuite chaque ligne de cette valeur spéciale (qui correspond à chaque ligne de la table) et on ajoute au fur et à mesure cette ligne au tableau eleves
qui contient alors un tableau de tableaux de chaînes de caractères représentant les données.
Remarque : il est aussi possible de construire le tableau eleves
par compréhension en remplaçant les lignes 4, 5 et 6 par l'instruction eleves =[ligne for ligne in t]
. Voyez pas vous-même :
import csv
fichier = open('eleves.csv', 'r', encoding = 'UTF-8')
t = csv.reader(fichier, delimiter=',')
eleves = [ligne for ligne in t] # création et construction du tableau par compréhension
print(eleves) # pour afficher le contenu du tableau 'table'
Comme on le voit, cette solution n'est pas forcément satisfaisante.
Tout d'abord, la première ligne contenant les attributs a été chargée comme une ligne de données. Il faudra prendre soin de l'ignorer durant les traitements ou de lire la première ligne du fichier avant en ajoutant le code suivant entre les lignes 2 et 3 (essayez de le faire)
fichier.readline()
Ce code permet de lire la première ligne et de positionner le curseur de lecture sur la seconde ligne qui sera la prochaine ligne à lire.
Deuxièmement, on constate que toutes les données ont été considérées comme des chaînes de caractères, même les nombres entiers.
eleves[1][4]
. Il faut donc se souvenir de la correspondance entre le nom de l'attribut et sa position dans le tableau.eleves[1][4] # pensez à exécuter le code précédent si un message d'erreur apparaît
On considère la table précédente mémorisée dans un tableau de tableaux. Exécutez à nouveau le code du début du paragraphe 1) avant de commencer l'exercice.
Une alternative, qui va remédier aux deux premiers problèmes, consiste à utiliser la fonction DictReader
du module csv
. Elle s'utilise de manière identique et va permettre de mémoriser les données dans un tableau de dictionnaires.
import csv
fichier = open('eleves.csv', 'r', encoding = 'UTF-8')
t = csv.DictReader(fichier, delimiter=',')
eleves = [] # on va mémoriser les données dans le tableau 'eleves'
for ligne in t:
eleves.append(dict(ligne))
print(eleves) # pour afficher le contenu du tableau 'eleves'
Remarques :
eleves
contient désormais un tableau de dictionnaires.eleves[1]['sexe']
dict
à la ligne 6 du programme précédent car sans elle, on aurait obtenu un tableau de dictionnaires ordonnés (pour les dernières versions de Python) mais dont l'affichage est un peu moins joli. Vous pouvez essayer d'enlever la fonction dict
sur cette ligne pour voir par vous-même. En revanche, on utiliserait le dictionnaire ordonné obtenu de la même façon : on accèderait au sexe du deuxième élève avec l'intruction eleves[1]['sexe']
comme précédemment.eleves
par compréhension :import csv
fichier = open('eleves.csv', 'r', encoding = 'UTF-8')
t = csv.DictReader(fichier, delimiter=',')
eleves = [dict(ligne) for ligne in t] # création et construction du tableau par compréhension
print(eleves) # pour afficher le contenu du tableau 'eleves'
On considère la table précédente mémorisée dans un tableau de dictionnaires. Exécutez à nouveau le code du début du paragraphe 2) avant de commencer l'exercice.
Après avoir fait les exercices 2 et 3, vous devez constater que la mémorisation dans un tableau de dictionnaires est plus pratique pour y rechercher des informations, au sens où l'on n'a pas besoin de connaître l'index de l'information cherchée (5 par exemple pour le projet) mais uniquement sa clé ('projet').
Cependant, ce n'est pas encore parfait car pour trouver l'année de naissance de Mathis, il faut savoir que la ligne le concernant a pour index 13 dans le tableau. Imaginez ce que cela peut donner pour trouver un index dans des fichiers de plusieurs dizaines de milliers de lignes...
Heureusement, il est possible de chercher plus efficacement des données dans une table, c'est ce que nous allons voir maintenant.
Une fois les données chargées dans une table, il est possible de travailler sur ces données en utilisant les opérations de manipulation sur les tableaux et les dictionnaires.
Dans ce paragraphe et dans toute la suite, nous allons supposer que les données ont été chargées dans un tableau de dictionnaires comme vu dans le paragraphe I. B. 2. Sachez cependant qu'il est possible de réaliser le même genre de choses sur des tableaux de tableaux mais il faut connaître les index des attributs, ce qui est plus fastidieux.
On cherche ici à rechercher la présence d'un élément dans une table (un élève dans notre cas). Nous allons utiliser des techniques de recherche dans un tableau comme celles vues au chapitre 2 de la séquence 3. Pour rappel, voici la fonction qui renvoie True
ou False
selon la présence ou l'absence d'un élément v
dans un tableau T
.
def appartient(v, T):
for e in T:
if e == v:
return True
return False
On va légèrement adapter cette fonction pour chercher un élève désigné par son prénom dans notre table.
def appartient(p, eleves):
''' p est un chaîne de caractères et eleves est un tableau de dictionnaires '''
for e in eleves:
if e['prénom'] == p:
return True
return False
Explications : on passe en revue tous les éléments du tableau (chaque dictionnaire) et on teste si l'un d'entre eux possède un attribut 'prénom' égal à p
, autrement dit si un des élèves a le prénom p
.
On peut alors appeler cette fonction pour tester la présence d'un élève. S'il y a un souci, vous exécuterez à nouveau le premier programme du paragraphe II. B. 2 qui va mémoriser les données dans eleves
.
appartient('Haude', eleves) # est-ce que 'Haude' est dans 'eleves' ?
appartient('Lucas', eleves) # est-ce que 'Lucas' est dans 'eleves' ?
On peut adapter la fonction précédente pour qu'elle renvoie le projet de l'élève dont le prénom p
est entré en paramètre.
def projet_de(p, eleves):
''' p est un chaîne de caractères et eleves est un tableau de dictionnaires '''
for e in eleves:
if e['prénom'] == p: # si un élève a le prénom p
return e['projet'] # on renvoie le projet de cet élève
projet_de('Leo', eleves)
Remarque : Si le prénom n'est pas dans eleves
, cette fonction renvoie None
.
Ecrire une fonction qui renvoie le sexe d'un élève de la table eleves
dont le prénom p
est entré en paramètre.
Il est possible de préciser la recherche en combinant les conditions sur plusieurs attributs.
def nom_eleve(a, m, eleves):
''' a et m sont des chaînes de caractères et eleves est un tableau de dictionnaires '''
for e in eleves:
if e['année'] == a and e['mois'] == m: # si un élève est né l'année a et le mois m
return e['prénom'] # on renvoie le prénom de cet élève
nom_eleve('2003', '3', eleves)
Remarques :
int
dans la fonction de manière à comparer des variables de même type.def nom_eleve_bis(a, m, eleves):
''' a et m sont des entiers et eleves est un tableau de dictionnaires '''
for e in eleves:
if int(e['année']) == a and int(e['mois']) == m: # conversion avec la fonction int
return e['prénom']
nom_eleve_bis(2003, 3, eleves) # on peut utiliser des paramètres entiers
Sans l'exécuter, que permet de faire la fonction suivante ?
def mystere(a, s, eleves):
''' a et s sont des chaînes de caractères et eleves est un tableau de dictionnaires '''
for e in eleves:
if e['année'] == a and e['sexe'] == s:
return e['prénom']
Réponse :
Ecrire une fonction age_de(p, eleves)
qui renvoie l'âge d'un élève de la table eleves
dont le prénom p
est entré en paramètre.
prop(a, eleves)
qui renvoie la proportion d'élèves de la table eleves
nés l'année a
. On considérera que a
est une chaîne de caractères.
Toutes les opérations précédentes permettent de produire des résultats simples : afficher le projet d'un élève, afficher le sexe d'un élève, afficher un nombre d'occurences.
Or, dans le domaine du traitement de données, il est très souvent nécessaire d'extraire différentes données d'une table pour en construire une nouvelle. Par exemple, extraire tous les élèves qui sont nés un mois donné afin de leur souhaiter un bon anniversaire.
Pour cela, il suffit de sélectionner les lignes vérifiant une certaine condition pour produire une nouvelle table. Pour créer cette nouvelle table, deux possibilités s'offrent à vous:
# CONSTRUCTION PAR COMPREHENSION
t = [e for e in eleves if e['mois'] == '2']
t # affichage du résultat
# CONSTRUCTION AVEC UNE BOUCLE
t = [] # on part d'un tableau vide que l'on complète au fur et à mesure
for e in eleves:
if e['mois'] == '2':
t.append(e)
t # affichage du résultat
Explication : le tableau t
ainsi construit contient tous les dictionnaires des élèves de la table eleves
qui sont nés en février.
eleves
, contruire une table t0
contenant tous les garçons de la classe.
eleves
, contruire une table t1
contenant les élèves nés en janvier.
eleves
, contruire une table t2
contenant les élèves nés en janvier 2003.
eleves
, contruire une table t3
contenant les élèves nés entre le 1er janvier 2003 et le 5 mai 2003.
Dans le paragraphe précédent, vous avez vu comment construire une nouvelle table en sélectionnant certaines des lignes d'une autre table. Cela signifie que toutes les colonnes des lignes sélectionnées ont été ajoutées à la table créée. On peut aussi très facilement construire un nouveau tableau ne contenant que certaines colonnes de la table de départ.
Par exemple, si on souhaite construire un tableau avec uniquement le prénom des élèves de la classe, on ne va sélectionner que la colonne contenant le prénom. La construction est la suivante :
t = [e['prénom'] for e in eleves]
t
On dit que l'on a fait une projection sur la colonne contenant les prénoms des élèves.
Il est bien sûr possible de combiner une sélection sur les colonnes avec une sélection sur les lignes. Ainsi, l'instruction
t = [e['prénom'] for e in eleves if e['sexe'] == 'G']
t
permet de créer un tableau contenant les prénoms des garçons de la classe. On a donc sélectionné la première colonne contenant les prénoms des élèves mais seulement des lignes correspondant à des garçons.
A partir de la table eleves
construire un tableau t1
contenant les prénoms des élèves nés en 2003. (Maxime et Raphaël ne doivent pas s'y trouver).
Le principal objectif des projections est de pouvoir constuire une nouvelle table à partir de certaines colonnes de la table de départ. Pour cela, au lieu d'extraire la valeur d'un seul attribut, on peut construire un nouveau dictionnaire à partir de plusieurs attributs. Ainsi, l'instruction
t = [{'prénom': e['prénom'], 'projet': e['projet']} for e in eleves]
t
construit pour chaque ligne de la table eleves
un dictionnaire contenant un attribut 'prénom' et un attribut 'projet' dont les valeurs sont exactement les valeurs des attributs de même nom dans la ligne considérée. Autrement dit, on extrait de la table eleves
une table ne conservant que les prénoms et les projets. On dit que l'on a effectué une projection sur ces 2 colonnes.
t1
ne conservant que les prénoms et les années de naissance des élèves de la table eleves
.
t2
contenant les prénoms, les années de naissance et l'âge des élèves.
t3
ne contenant que les prénoms et les projets des élèves nés entre janvier et mars 2003.
Grâce au module csv
de Python, il est également très facile d'écrire dans un fichier CSV. Imaginons qu'à partir du fichier "eleves.csv" initial, on souhaite créer un nouveau fichier CSV contenant uniquement les prénoms des élèves nés en 2003 ainsi que leurs projets.
On peut commencer par sélectionner les lignes et colonnes souhaitées et les stocker dans un tableau :
ma_table = [{'prénom': e['prénom'], 'projet': e['projet']} for e in eleves if int(e['année']) == 2003]
ma_table
Pour enregistrer cette table dans un fichier CSV, il suffit d'ouvrir un fichier en écriture et d'utiliser la fonction DictWriter
comme suit
sortie = open("projets_eleves_2003.csv", "w", newline = '', encoding = "utf-8")
w = csv.DictWriter(sortie, ['prénom', 'projet'])
w.writeheader()
w.writerows(ma_table)
sortie.close()
Explications :
"w"
indique que le fichier est ouvert en écriture (w pour write en anglais), la paramètre newline
est mis à ''
pour éviter un saut de ligne entre chacune des lignes du fichier.DictWriter
en lui donnant en paramètres le fichier ouvert en écriture ainsi que la liste des attributs. Cette fonction renvoie un objet w
permettant d'écrire des lignes dans le fichier.w.writerows(ma_table)
permet d'écrire les lignes de ma_table
dans le fichier.Vous devez constater qu'un fichier CSV nommé "projets_eleves_2003.csv" a été créé dans le repertoire du notebook. Ouvrez celui-ci avec un éditeur de texte puis avec un tableur en prenant soin de vérifier que le caractère de séparation du tableur est bien la virgule.
Remarque : Il est aussi possible de ne pas utiliser writerows
et d'écrire le fichier ligne à ligne avec la fonction writerow
(sans s) avec une boucle for
qui parcoure chaque ligne de la table et l'écrit dans le fichier au fur et à mesure.
sortie = open("projets_eleves_2003.csv", "w", newline = '', encoding = "utf-8")
w = csv.DictWriter(sortie, ['prénom', 'projet'])
w.writeheader()
for e in ma_table: # ce deux lignes ont le même rôle que 'writerows'
w.writerow(e)
sortie.close()
tab
contenant les prénoms, les projets et l'âge des filles de la classe.
Nous avons vu que les données étaient mémorisées sous forme de chaînes de caractères, même les informations qui sont des nombres (le jour, le mois et l'année de naissance dans notre exemple). On peut s'en sortir en veillant à convertir ces données en de vrais nombres Python lorsque c'est nécessaire, comme nous l'avons fait à certaines reprises avec la fonction int
.
Pour éviter d'oublier de faire ces conversions lors des différents traitements, il est possible de convertir les données de la table avant de chercher ou sélectionner des lignes / colonnes dans celle-ci.
Une façon de procéder est de définir une fonction conversion
qui prend en paramètre un dictionnaire et qui renvoie un dictionnaire avec les valeurs converties.
def conversion(d):
return {'prénom': d['prénom'], 'jour': int(d['jour']), 'mois': int(d['mois']), 'année': int(d['année']), 'sexe': d['sexe'], 'projet': d['projet']}
On peut alors parcourir la table eleves
et appliquer à chaque dictionnaire la fonction conversion
. On stocke la table convertie dans une variable appelée eleves_convertie
. Par compréhension cela donne
eleves_convertie = [conversion(e) for e in eleves]
eleves_convertie
On peut aussi construire table_convertie
avec une boucle comme ce qui suit :
eleves_convertie = []
for e in eleves:
eleves_convertie.append(conversion(e))
eleves_convertie
Retenir : Cela peut être une bonne pratique de convertir les données de la table juste après l'avoir mémorisée. En effet, c'est fait dès le départ et cela évite de se demander à chaque traitement s'il faut ou non convertir les données et d'éventuellement de se tromper.
Par exemple, en travaillant avec table_convertie
on peut construire une table contenant les prénoms et l'âge des élèves nés avant le 25 février de manière plus simple.
tab = [{'prénom': e['prénom'], 'âge': 2019 - e['année']} for e in eleves_convertie if e['mois'] == 1 or e['mois'] == 2 and e['jour'] <= 25]
tab
Nous avons travaillé sur une table dont les données sont correctes mais il faut souvent se méfier. En effet, une simple faute de frappe dans la saisie des données du fichier CSV
peut avoir des répercussions importantes, et ce n'est pas rare.
Si par mégarde on a saisi comme jour de naissance pour un élève la valeur '34'
au lieu de '24'
, alors la table contient une valeur incohérente. De même, si dans la saisie des données on a oublié de rentrer une valeur pour le mois de naissance, les données seront incohérentes (car il y aurait un décalage dans les valeurs : l'année deviendrait le mois, le projet deviendrait l'année, et le projet n'aurait pas de valeur). Dans les deux cas, selon les traitements effectués, il est possible de provoquer des erreurs.
Une façon d'éviter ces soucis est de tester la cohérence de chaque dictionnaire afin de ne conserver que les lignes valides. A première vue, pour vérifier si une ligne de la table eleves
est cohérente on peut vérifier que le jour est compris entre 1 et 31, le mois entre 1 et 12 et l'année inférieure ou égale à 2020. Pour se faire, la fonction est_coherente
suivante va faire le travail :
def est_coherent(e):
jour = int(e['jour'])
mois = int(e['mois'])
annee = int(e['année'])
if 1 <= jour <= 31 and 1 <= mois <= 12 and annee <= 2020:
return True
else:
return False
On peut alors vérifier cette fonction grâce à l'instruction suivante :
table_coherente = [e for e in eleves if est_coherent(e)]
print(table_coherente)
len(table_coherente) # pour vérifier qu'il y a bien 16 élèves dans table_coherente
Explication : on a créé une table appelée table_coherente
qui contient les lignes de la table eleves
qui sont cohérentes. On a aussi affiché la taille de table_coherente
pour vérifier qu'il y a bien 16 élèves (et donc que toutes les lignes sont cohérentes).
Imaginons désormais que l'on ait entré la valeur '1é'
au lieu de '12'
pour le mois de naissance de Valentin. Dans ce cas, cela peut provoquer des erreurs dans les traitements souhaités : l'extraction des éléves nés en décembre risque de renvoyer une erreur. Pire encore, la fonction est_coherente
précédente sera interrompue car '1é'
ne peut pas être converti en un entier (ligne 3) et aucune table ne sera produite.
Avant de convertir les valeurs en des entiers il est donc nécessaire de vérifier qu'il s'agit d'une chaîne de caractère qui représente bien un nombre. La méthode isdecimal
fait ce travaille : elle renvoie True
si c'est le cas et False
sinon.
ch1 = '12'
print(ch1.isdecimal())
ch2 = '1é'
print(ch2.isdecimal())
On peut alors améliorer la fonction est_coherente
de la façon suivante
def est_coherente(e):
jour = e['jour'] # on ne convertit pas de suite le jour, le mois et l'année
mois = e['mois']
annee = e['année']
if jour.isdecimal() and mois.isdecimal() and annee.isdecimal() and 1 <= int(jour) <= 31 and 1 <= int(mois) <= 12 and int(annee) <= 2019:
return True
else:
return False
ou de manière un peu plus synthétique comme cela :
def est_coherente(e):
jour = e['jour'] # on ne convertit pas de suite le jour, le mois et l'année
mois = e['mois']
annee = e['année']
return jour.isdecimal() and mois.isdecimal() and annee.isdecimal() and 1 <= int(jour) <= 31 and 1 <= int(mois) <= 12 and int(annee) <= 2019
eleves
. table_cohérente
.eleves_coherente = [e for e in eleves if est_coherent(e)]
print(eleves_coherente)
len(eleves_coherente)
table_coherente
ne contient que les lignes cohérentes.Vous constaterez que dans l'exercice 12, les données n'ont pas été converties en des entiers. En effet, la fonction est_coherente
ne se contente que de tester si une ligne est cohérente c'est-à-dire si les valeurs entrées pour le jour, le mois et l'année représentent bien des entiers et si les valeurs de ces entiers sont cohérentes.
En combinant cette fonction avec la fonction conversion
du paragraphe 1, on peut créer un tableau ne contenant que des lignes valides, c'est-à-dire des lignes qui sont à la fois cohérente et qui ont été converties.
Il suffit de construire la table valide par compréhension de la façon suivante :`
eleves_validee = [conversion(e) for e in eleves if est_coherente(e)]
eleves_validee
Il s'agit de la même construction que dans le paragraphe A (du IV) mais avec la condition supplémentaire que la ligne doit être cohérente pour qu'elle soit convertie et ajouté à eleves_validee
.
Commencez par télécharger sur le site info-mounier.fr le fichier "population_pdl.csv" qui contient des informations sur la population des communes de la région Pays de la Loire.
Ce fichier est aussi disponible en open data sur le site data.maine-et-loire.fr. Comme indiqué sur cette page Web, le caractère de séparation est le point-virgule.
Réponse :
communes
.
communes_2015 = [e for e in communes if ..................]
table_communes
qui ne conserve que ces trois colonnes de la table communes_2015
table_communes
pour que le nom des attributs soient plus simplement : 'dep', 'commune' et 'population'.
float
puis convertir le flottant obtenu avec int
.
Si vous êtes arrivés jusque là, bravo ! Vous allez maintenant pouvoir travailler sur cette table appelée table_communes
.
def fonction_mystere(c, table_communes):
''' c est une chaîne de caractères et table_communes est un tableau de dictionnaires '''
for e in table_communes:
if e['commune'] == c:
return e['population']
Réponse :
departement_de(c, table_communes)
qui renvoie le département d'une commune c
de tables_communes
.
nb_communes_ML
qui prend en paramètre la table table_communes
et qui renvoie le nombre de communes du département du Maine-et-Loire
communes_LA
qui ne contient que les lignes des communes du département de Loire-Atlantique.
communes_LAbis
qui ne contient plus que les deux dernière colonnes (nom de la commune et population).
grosses_communes_ML
qui ne contient que les communes de plus de 5000 habitants de Maine-et-Loire.
grosses_communes_ML
et communes_LAbis
dans des fichiers CSV différents et ouvrez les fichiers créés avec un tableur pour en vérifier le contenu.
Le format JSON (Java Script Object Notation) permet de mémoriser dans un fichier texte et de relire, les principaux types de données utilisés en python : listes, tuples, dictionnaire et bien sûr les types de base entiers, flottants, chaînes et booléens.
C'est une alternative intéressante aux formats tabulés quand l'information à mémoriser a une structure plus complexe qu'une table à double entrées. L'intérêt est aussi de fournir une représentation externe des informations manipulées, dans un format normalisé pouvant être utilisé par d'autres programmes écrits dans d'autres langages.
En pratique, les fichiers JSON sont particulièrement utilisés pour structurer et transmettre des données sur le Web : on peut par exemple récupérer les données ouvertes en temps réels (au format JSON) du nombre de places de parking disponibles à Angers les analyser et les afficher sur un beau site Web au design soigné (c'est une idée de projet pour vous).
Voici quelques éléments pour présenter le format.
repertoire = [{'Nom':'Dupont', 'Prenom':'Jean', 'Naissance':{'Jour':10, 'Mois':2, 'Annee':1984}},
{'Nom':'Durand', 'Prenom':'Marie', 'Naissance':{'Jour':21, 'Mois':12, 'Annee':1964}},
{'Nom':'Dupond', 'Prenom':'Pierre', 'Naissance':{'Jour':1, 'Mois':8, 'Annee':1960}}]
La fonction json.dump
permet d'écrire dans un fichier au format JSON
une structure de données calculée par programme.
import json
f = open('repertoire.json', 'w')
json.dump(repertoire, f)
f.close()
Le fichier texte généré est lisible avec un éditeur de texte et peut aussi être relu par programme avec la fonction json.load
.
g = open('repertoire.json', 'r')
nouveaurep = json.load(g)
nouveaurep
On a ainsi avec le format JSON
une technique performante pour mémoriser dans des fichiers des informations structurées et les retrouver sans perte d'information.
import json
fichier = open('parking-angers.json')
parkings=json.loads(fichier.read())
fichier.close()
parkings
La maîtrise de la lecture d'un fichier de données est un préalable à son traitement. L'écriture est aussi importante pour garder une trace pérenne des informations calculées.
Pour les données ouvertes obtenues sur des sites spécialisés, il convient d'être vigilant en cas de données manquantes ou de données particulières, et de prévoir un prétraitement adapté.
Sources :
Germain BECKER & Sébastien POINT, Lycée Mounier, ANGERS