Cours de NSI Première

Constructions élémentaires Booléens Fonctions Chaînes de caractères Tableaux p-uplets et dictionnaires Tables de données Flottants Algorithmes classiques Index Énoncés

Chapitre 7 : Tables de données

Importation d'une table depuis un fichier CSV, recherche dans une table, tri d'une table, fusion de tables

Partie A - Représentation de données en tables

Une des utilisations principales de l’informatique de nos jours est le traitement de quantités importantes de données dans des domaines très variés. Par exemple, un site de commerce en ligne peut avoir à gérer des bases de données pour des dizaines de milliers d’articles en vente, de clients, de commandes. Un hopital doit pouvoir accéder efficacement à tous les détails de traitements de ses patients, etc.

Mais si les logiciels de traitement de base de données sont des programmes hautement spécialisés pour effectuer ce genre de tâches le plus efficacement possible, il est facile de mettre en œuvre les opérations de base dans un langage de programmation comme Python. C'est l'objectif de ce chapitre.

Format CSV

Le format CSV (pour comma separated values, c'est-à-dire valeurs séparées par des virgules) est un format de fichier texte très pratique pour représenter des données structurées. Dans ce format, chaque ligne représente un enregistrement et chaque colonne représente un champ de l’enregistrement. Les champs sont séparés par une virgule, d’où le nom CSV.

En pratique, on peut choisir le caractère utilisé pour séparer les différents champs et on utilise parfois, plutôt qu'une virgule, un point-virgule, une tabulation, deux points ou une barre verticale. Nous pouvons enfin remarquer que la première ligne d’un tel fichier est généralement utilisée pour indiquer le nom des différents champs. Dans ce cas, le premier enregistrement apparaît sur la deuxième ligne du fichier et non sur la première.

Dans tout ce chapitre, nous utiliserons les données contenues dans le fichier prefectures.csv, dont voici les 20 premières lignes :

dep,ville,dep_nom,lat,long,CL_reg
1,Bourg-en-Bresse,Ain,46.202500000000001,5.221944444444444,0
2,Laon,Aisne,49.562222222222225,3.622500000000000,0
3,Moulins,Allier,46.568333333333335,3.334444444444444,0
4,Digne-les-Bains,Alpes-de-Haute-Provence,44.092222222222219,6.238055555555555,0
5,Gap,Hautes-Alpes,44.557499999999997,6.076111111111111,0
6,Nice,Alpes-Maritimes,43.696388888888890,7.275000000000000,0
7,Privas,Ardèche,44.735277777777775,4.599444444444444,0
8,Charleville-Mézières,Ardennes,49.761388888888888,4.720000000000000,0
9,Foix,Ariège,42.967222222222219,1.605833333333333,0
10,Troyes,Aube,48.297777777777775,4.078333333333333,0
11,Carcassonne,Aude,43.214722222222221,2.353333333333333,0
12,Rodez,Aveyron,44.349444444444444,2.574722222222222,0
13,Marseille,Bouches-du-Rhône,43.290277777777774,5.380000000000000,1
14,Caen,Calvados,49.180000000000000,-0.365277777777778,0
15,Aurillac,Cantal,44.929166666666667,2.446944444444445,0
16,Angoulême,Charente,45.645833333333336,0.156944444444444,0
17,La Rochelle,Charente-Maritime,46.157499999999999,-1.157222222222222,0
18,Bourges,Cher,47.081111111111113,2.395277777777778,0
19,Tulle,Corrèze,45.271111111111111,1.768888888888889,0

Question 1 : Ouvrir avec un éditeur de texte le fichier prefectures.csv et décrire quel est le contenu du fichier. En particulier, quel est le nombre d'enregistrements, à quoi correspondent-ils, et quels en sont les différents champs ?

Le fichier prefectures.csv est un fichier CSV contenant 101 enregistrements, qui correspondent aux 101 départements français. Chaque enregistrement est composé des champs dep (numéro du département), ville (nom de la ville préfecture), dep_nom (nom du département), lat et long (coordonnées géographiques de la préfecture) et CL_reg (1 si la ville est chef-lieu de région et 0 sinon).

Importation d'une table depuis un fichier CSV

Pour pouvoir manipuler avec Python les données enregistrées dans le fichier CSV, il faut commencer par importer ces données et les stocker dans un tableau. Pour réaliser cette opération, on peut définir la fonction importer_donnees :

In [1]:
import csv

def importer_donnees(nom_de_fichier):
    """
    Importe les données contenues dans un fichier CSV et les retourne sous forme de tableau
    - Entrée : nom_de_fichier (chaîne de caractères correspondant à un nom de fichier CSV)
    - Sortie : tab (tableau de dictionnaires, correspondant aux enregistrements du fichier CSV)
    Attention : les données importées sont de type chaîne de caractères
    """
    tab = []
    with open(nom_de_fichier, 'r', encoding = 'utf-8') as fichier:
        donnees = csv.DictReader(fichier, delimiter = ',')
        for enregistrement in donnees:
            tab.append(dict(enregistrement))
    return tab
In [2]:
pref = importer_donnees('prefectures.csv')
La commande with open(nom_de_fichier, 'r', encoding = 'utf-8'), déjà rencontrée dans le chapitre sur les chaînes de caractères, permet d'ouvrir le fichier en lecture en précisant que le texte est encodé au format UTF-8.
La fonction DictReader, importée du module csv, récupère les données depuis le fichier CSV et les stocke dans la variable donnees, qui est un itérable dont les éléments sont des dictionnaires ordonnés (type particulier de dictionnaire). Le paramètre optionnel delimiter permet d'indiquer par quel caractère sont séparés les champs dans le fichier CSV.
Les lignes 13 et 14 transforment l'itérable donnees en un tableau tab, et les dictionnaires ordonnés en simples dictionnaires.

Question 2 : Ecrire la spécification de la fonction importer_donnees.

Question 3 : Après avoir exécuté la cellule suivante et affiché les cinq premiers éléments de pref, dire quel est le type de ces éléments.

In [3]:
for k in range(5):
    print(pref[k])
{'dep': '1', 'ville': 'Bourg-en-Bresse', 'dep_nom': 'Ain', 'lat': '46.202500000000001', 'long': '5.221944444444444', 'CL_reg': '0'}
{'dep': '2', 'ville': 'Laon', 'dep_nom': 'Aisne', 'lat': '49.562222222222225', 'long': '3.622500000000000', 'CL_reg': '0'}
{'dep': '3', 'ville': 'Moulins', 'dep_nom': 'Allier', 'lat': '46.568333333333335', 'long': '3.334444444444444', 'CL_reg': '0'}
{'dep': '4', 'ville': 'Digne-les-Bains', 'dep_nom': 'Alpes-de-Haute-Provence', 'lat': '44.092222222222219', 'long': '6.238055555555555', 'CL_reg': '0'}
{'dep': '5', 'ville': 'Gap', 'dep_nom': 'Hautes-Alpes', 'lat': '44.557499999999997', 'long': '6.076111111111111', 'CL_reg': '0'}
pref est un tableau dont les éléments sont des dictionnaires. Tous les dictionnaires contenus dans pref ont les mêmes clés, à savoir 'dep', 'ville', 'dep_nom', 'lat', 'long' et 'CL_reg'.

On constate que, lors de l'importation, tous les champs sont des chaînes de caractères. Pour faire en sorte que la latitude et la longitude des différentes préfectures soit de type numérique, exécuter la cellule ci-dessous :

In [4]:
for k in range(len(pref)):
    pref[k]['lat'] = float(pref[k]['lat'])
    pref[k]['long'] = float(pref[k]['long'])

Question 4 : Ecrire des lignes de code permettant de faire en sorte que le champ 'CL_reg' soit de type booléen.

In [5]:
for k in range(len(pref)):
    pref[k]['CL_reg'] = bool(int(pref[k]['CL_reg']))
Après l'importation d'une table de données, cette étape de modification des types fait partie de ce que l'on appelle la validation des données. C'est une étape nécessaire pour pouvoir utiliser efficacement la table.

Partie B - Recherche dans une table

Une fois que la table est stockée en mémoire sous la forme d'un tableau de dictionnaires, il est possible d'effectuer des recherches dans la table.

Affichage de données

Par exemple, voici des lignes de code permettant d'afficher le nom des 101 départements français :

In [6]:
for k in range(len(pref)):
    print(pref[k]['dep_nom'], end = '  ')
Ain  Aisne  Allier  Alpes-de-Haute-Provence  Hautes-Alpes  Alpes-Maritimes  Ardèche  Ardennes  Ariège  Aube  Aude  Aveyron  Bouches-du-Rhône  Calvados  Cantal  Charente  Charente-Maritime  Cher  Corrèze  Corse-du-Sud  Haute-Corse  Côte-d'Or  Côtes-d'Armor  Creuse  Dordogne  Doubs  Drôme  Eure  Eure-et-Loir  Finistère  Gard  Haute-Garonne  Gers  Gironde  Hérault  Ille-et-Vilaine  Indre  Indre-et-Loire  Isère  Jura  Landes  Loir-et-Cher  Loire  Haute-Loire  Loire-Atlantique  Loiret  Lot  Lot-et-Garonne  Lozère  Maine-et-Loire  Manche  Marne  Haute-Marne  Mayenne  Meurthe-et-Moselle  Meuse  Morbihan  Moselle  Nièvre  Nord  Oise  Orne  Pas-de-Calais  Puy-de-Dôme  Pyrénées-Atlantiques  Hautes-Pyrénées  Pyrénées-Orientales  Bas-Rhin  Haut-Rhin  Rhône  Haute-Saône  Saône-et-Loire  Sarthe  Savoie  Haute-Savoie  Paris  Seine-Maritime  Seine-et-Marne  Yvelines  Deux-Sèvres  Somme  Tarn  Tarn-et-Garonne  Var  Vaucluse  Vendée  Vienne  Haute-Vienne  Vosges  Yonne  Territoire de Belfort  Essonne  Hauts-de-Seine  Seine-Saint-Denis  Val-de-Marne  Val-d'Oise  Guadeloupe  Martinique  Guyane  Réunion  Mayotte  

Question 5 : Ecrire des lignes de code permettant d'afficher le nom des villes préfectures.

In [7]:
for k in range(len(pref)):
    print(pref[k]['ville'], end = '  ')
Bourg-en-Bresse  Laon  Moulins  Digne-les-Bains  Gap  Nice  Privas  Charleville-Mézières  Foix  Troyes  Carcassonne  Rodez  Marseille  Caen  Aurillac  Angoulême  La Rochelle  Bourges  Tulle  Ajaccio  Bastia  Dijon  Saint-Brieuc  Guéret  Périgueux  Besançon  Valence  Évreux  Chartres  Quimper  Nîmes  Toulouse  Auch  Bordeaux  Montpellier  Rennes  Châteauroux  Tours  Grenoble  Lons-le-Saunier  Mont-de-Marsan  Blois  Saint-Étienne  Le Puy-en-Velay  Nantes  Orléans  Cahors  Agen  Mende  Angers  Saint-Lô  Châlons-en-Champagne  Chaumont  Laval  Nancy  Bar-le-Duc  Vannes  Metz  Nevers  Lille  Beauvais  Alençon  Arras  Clermont-Ferrand  Pau  Tarbes  Perpignan  Strasbourg  Colmar  Lyon  Vesoul  Mâcon  Le Mans  Chambéry  Annecy  Paris  Rouen  Melun  Versailles  Niort  Amiens  Albi  Montauban  Toulon  Avignon  La Roche-sur-Yon  Poitiers  Limoges  Épinal  Auxerre  Belfort  Évry  Nanterre  Bobigny  Créteil  Pontoise  Basse-Terre  Fort-de-France  Cayenne  Saint-Denis  Mamoudzou  

Question 6 : Ecrire des lignes de code permettant d'afficher le nom des départements dont la préfecture contient la lettre X.

In [8]:
for k in range(len(pref)):
    if 'x' in pref[k]['ville'].lower():
        print(pref[k]['dep_nom'], end = '  ')
Ariège  Dordogne  Eure  Gironde  Indre  Yonne  

Question 7 : Ecrire des lignes de code permettant d'afficher les préfectures dont la latitude est comprise entre 44° et 46° et dont la longitude est comprise entre 2° et 4°.

In [9]:
for k in range(len(pref)):
    if 44 <= pref[k]['lat'] <= 46 and 2 <= pref[k]['long'] <= 4:
        print(pref[k]['ville'], end = '  ')
Rodez  Aurillac  Le Puy-en-Velay  Mende  Clermont-Ferrand  

Question 8 : Ecrire des lignes de code permettant d'afficher le nom et les coordonnées géographiques des 18 capitales de région (arrondies à deux chiffres après la virgule).

In [10]:
for k in range(len(pref)):
    if pref[k]['CL_reg']:
        print(pref[k]['ville'], ':', round(pref[k]['lat'], 2), ';', round(pref[k]['long'], 2))
Marseille : 43.29 ; 5.38
Ajaccio : 41.92 ; 8.74
Dijon : 47.32 ; 5.04
Toulouse : 43.6 ; 1.45
Bordeaux : 44.84 ; -0.59
Rennes : 48.11 ; -1.67
Nantes : 47.22 ; -1.55
Orléans : 47.9 ; 1.91
Lille : 50.63 ; 3.06
Strasbourg : 48.59 ; 7.75
Lyon : 45.76 ; 4.84
Paris : 48.86 ; 2.35
Rouen : 49.45 ; 1.08
Basse-Terre : 15.99 ; -61.72
Fort-de-France : 14.61 ; -61.07
Cayenne : 4.94 ; -52.33
Saint-Denis : -20.88 ; 55.45
Mamoudzou : -12.78 ; 45.23

Comptage de données

Question 9 : Ecrire des lignes de code permettant compter le nombre de villes préfectures situées à l'ouest du méridien de Greenwich, c'est-à-dire dont la longitude est négative.

In [11]:
cpt = 0
for k in range(len(pref)):
    if pref[k]['long'] <= 0:
        cpt += 1
print('Il y a', cpt, 'préfectures à l\'ouest du méridien de Greenwich.')
Il y a 18 préfectures à l'ouest du méridien de Greenwich.

Question 10 : Ecrire des lignes de code permettant compter le nombre de villes préfectures situées au nord de Paris.

In [12]:
k = 0
while pref[k]['ville'] != 'Paris':
    k += 1
long_Paris = pref[k]['lat']
cpt = 0
for k in range(len(pref)):
    if pref[k]['lat'] > long_Paris:
        cpt += 1
print('Il y a', cpt, 'préfectures au nord de Paris.')
Il y a 15 préfectures au nord de Paris.

Partie C - Tri d'une table

Pour exploiter les données, il peut être intéressant de les trier. Une utilisation possible est l’obtention du classement des entrées selon tel ou tel critère.

On ne peut pas directement trier le tableau pref. Il faut indiquer selon quels critères on veut effectuer ce tri. Pour cela, on commence par définir une fonction qui renvoie la valeur utilisée pour le tri.

Concrètement, si on souhaite trier la table pref en fonction de la latitude de la ville préfecture, on commence par définir la fonction suivante :

In [13]:
def cle_latitude(d):
    """
    Retourne la valeur associée à la clé 'lat' dans le dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'lat')
    - Sortie : (nombre)
    """
    return d['lat']

Pour trier la table, il suffit alors d'utiliser la commande .sort() avec le paramètre optionnel key égal à la fonction de tri définie précédemment :

In [14]:
pref.sort(key = cle_latitude)

On peut alors afficher la liste des préfectures dans l'ordre croissant de leur latitude, c'est-à-dire du sud au nord :

In [15]:
for k in range(len(pref)):
    print(pref[k]['ville'], end = '  ')
Saint-Denis  Mamoudzou  Cayenne  Fort-de-France  Basse-Terre  Ajaccio  Perpignan  Bastia  Foix  Toulon  Carcassonne  Tarbes  Marseille  Pau  Toulouse  Montpellier  Auch  Nice  Nîmes  Mont-de-Marsan  Albi  Avignon  Montauban  Digne-les-Bains  Agen  Rodez  Cahors  Mende  Gap  Privas  Bordeaux  Aurillac  Valence  Le Puy-en-Velay  Périgueux  Grenoble  Tulle  Saint-Étienne  Chambéry  Angoulême  Lyon  Clermont-Ferrand  Limoges  Annecy  La Rochelle  Guéret  Bourg-en-Bresse  Mâcon  Niort  Moulins  Poitiers  La Roche-sur-Yon  Lons-le-Saunier  Châteauroux  Nevers  Bourges  Nantes  Besançon  Dijon  Tours  Angers  Blois  Vesoul  Belfort  Vannes  Auxerre  Orléans  Quimper  Le Mans  Laval  Colmar  Rennes  Chaumont  Épinal  Troyes  Alençon  Chartres  Saint-Brieuc  Melun  Strasbourg  Évry  Nancy  Bar-le-Duc  Créteil  Versailles  Paris  Nanterre  Bobigny  Châlons-en-Champagne  Évreux  Pontoise  Saint-Lô  Metz  Caen  Beauvais  Rouen  Laon  Charleville-Mézières  Amiens  Arras  Lille  

Si l'on préfère afficher les villes du nord au sud, et donc par ordre décroissant des latitudes, on rajoute à la commande .sort() le paramètre optionnel reverse :

In [16]:
pref.sort(key = cle_latitude, reverse = True)
In [17]:
for k in range(len(pref)):
    print(pref[k]['ville'], end = '  ')
Lille  Arras  Amiens  Charleville-Mézières  Laon  Rouen  Beauvais  Caen  Metz  Saint-Lô  Pontoise  Évreux  Châlons-en-Champagne  Bobigny  Nanterre  Paris  Versailles  Créteil  Bar-le-Duc  Nancy  Évry  Strasbourg  Melun  Saint-Brieuc  Chartres  Alençon  Troyes  Épinal  Chaumont  Rennes  Colmar  Laval  Le Mans  Quimper  Orléans  Auxerre  Vannes  Belfort  Vesoul  Blois  Angers  Tours  Dijon  Besançon  Nantes  Bourges  Nevers  Châteauroux  Lons-le-Saunier  La Roche-sur-Yon  Poitiers  Moulins  Niort  Mâcon  Bourg-en-Bresse  Guéret  La Rochelle  Annecy  Limoges  Clermont-Ferrand  Lyon  Angoulême  Chambéry  Saint-Étienne  Tulle  Grenoble  Périgueux  Le Puy-en-Velay  Valence  Aurillac  Bordeaux  Privas  Gap  Mende  Cahors  Rodez  Agen  Digne-les-Bains  Montauban  Avignon  Albi  Mont-de-Marsan  Nîmes  Nice  Auch  Montpellier  Toulouse  Pau  Marseille  Tarbes  Carcassonne  Toulon  Foix  Bastia  Perpignan  Ajaccio  Basse-Terre  Fort-de-France  Cayenne  Mamoudzou  Saint-Denis  

Question 11 : Ecrire des lignes de code permettant d'afficher les préfectures françaises d'ouest en est.

In [18]:
def cle_longitude(d):
    """
    Retourne la valeur associée à la clé 'long' dans le dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'long')
    - Sortie : (nombre)
    """
    return d['long']

pref.sort(key = cle_longitude)

for k in range(len(pref)):
    print(pref[k]['ville'], end = '  ')
Basse-Terre  Fort-de-France  Cayenne  Quimper  Saint-Brieuc  Vannes  Rennes  Nantes  La Roche-sur-Yon  La Rochelle  Saint-Lô  Laval  Bordeaux  Angers  Mont-de-Marsan  Niort  Pau  Caen  Tarbes  Alençon  Angoulême  Le Mans  Poitiers  Auch  Agen  Tours  Périgueux  Rouen  Évreux  Limoges  Blois  Montauban  Cahors  Toulouse  Chartres  Foix  Châteauroux  Tulle  Guéret  Orléans  Beauvais  Pontoise  Versailles  Albi  Nanterre  Amiens  Paris  Carcassonne  Bourges  Évry  Aurillac  Bobigny  Créteil  Rodez  Melun  Arras  Perpignan  Lille  Clermont-Ferrand  Nevers  Moulins  Mende  Auxerre  Laon  Montpellier  Le Puy-en-Velay  Troyes  Nîmes  Châlons-en-Champagne  Saint-Étienne  Privas  Charleville-Mézières  Avignon  Mâcon  Lyon  Valence  Dijon  Chaumont  Bar-le-Duc  Bourg-en-Bresse  Marseille  Lons-le-Saunier  Grenoble  Chambéry  Toulon  Besançon  Gap  Annecy  Vesoul  Metz  Nancy  Digne-les-Bains  Épinal  Belfort  Nice  Colmar  Strasbourg  Ajaccio  Bastia  Mamoudzou  Saint-Denis  

Question 12 : Ecrire des lignes de code permettant d'afficher les capitales régionales françaises du nord au sud.

In [19]:
pref.sort(key = cle_latitude, reverse = True)

for k in range(len(pref)):
    if pref[k]['CL_reg']:
        print(pref[k]['ville'], end = '  ')
Lille  Rouen  Paris  Strasbourg  Rennes  Orléans  Dijon  Nantes  Lyon  Bordeaux  Toulouse  Marseille  Ajaccio  Basse-Terre  Fort-de-France  Cayenne  Mamoudzou  Saint-Denis  

En utilisant la commande .sort(), nous avons modifié la table pref en mémoire : l'index de chaque dictionnaire a été modifié dans le tableau pref. Si on souhaite garder intact la table initiale, il faut utiliser la fonction sorted() à la place de la commande .sort() :

In [20]:
pref = importer_donnees('prefectures.csv')

for k in range(len(pref)):
    pref[k]['lat'] = float(pref[k]['lat'])
    pref[k]['long'] = float(pref[k]['long'])
    pref[k]['CL_reg'] = bool(int(pref[k]['CL_reg']))

pref2 = sorted(pref, key = cle_latitude, reverse = True)
In [21]:
for k in range(len(pref)):
    print(pref[k]['ville'], end = '  ')
Bourg-en-Bresse  Laon  Moulins  Digne-les-Bains  Gap  Nice  Privas  Charleville-Mézières  Foix  Troyes  Carcassonne  Rodez  Marseille  Caen  Aurillac  Angoulême  La Rochelle  Bourges  Tulle  Ajaccio  Bastia  Dijon  Saint-Brieuc  Guéret  Périgueux  Besançon  Valence  Évreux  Chartres  Quimper  Nîmes  Toulouse  Auch  Bordeaux  Montpellier  Rennes  Châteauroux  Tours  Grenoble  Lons-le-Saunier  Mont-de-Marsan  Blois  Saint-Étienne  Le Puy-en-Velay  Nantes  Orléans  Cahors  Agen  Mende  Angers  Saint-Lô  Châlons-en-Champagne  Chaumont  Laval  Nancy  Bar-le-Duc  Vannes  Metz  Nevers  Lille  Beauvais  Alençon  Arras  Clermont-Ferrand  Pau  Tarbes  Perpignan  Strasbourg  Colmar  Lyon  Vesoul  Mâcon  Le Mans  Chambéry  Annecy  Paris  Rouen  Melun  Versailles  Niort  Amiens  Albi  Montauban  Toulon  Avignon  La Roche-sur-Yon  Poitiers  Limoges  Épinal  Auxerre  Belfort  Évry  Nanterre  Bobigny  Créteil  Pontoise  Basse-Terre  Fort-de-France  Cayenne  Saint-Denis  Mamoudzou  
In [22]:
for k in range(len(pref2)):
    print(pref2[k]['ville'], end = '  ')
Lille  Arras  Amiens  Charleville-Mézières  Laon  Rouen  Beauvais  Caen  Metz  Saint-Lô  Pontoise  Évreux  Châlons-en-Champagne  Bobigny  Nanterre  Paris  Versailles  Créteil  Bar-le-Duc  Nancy  Évry  Strasbourg  Melun  Saint-Brieuc  Chartres  Alençon  Troyes  Épinal  Chaumont  Rennes  Colmar  Laval  Le Mans  Quimper  Orléans  Auxerre  Vannes  Belfort  Vesoul  Blois  Angers  Tours  Dijon  Besançon  Nantes  Bourges  Nevers  Châteauroux  Lons-le-Saunier  La Roche-sur-Yon  Poitiers  Moulins  Niort  Mâcon  Bourg-en-Bresse  Guéret  La Rochelle  Annecy  Limoges  Clermont-Ferrand  Lyon  Angoulême  Chambéry  Saint-Étienne  Tulle  Grenoble  Périgueux  Le Puy-en-Velay  Valence  Aurillac  Bordeaux  Privas  Gap  Mende  Cahors  Rodez  Agen  Digne-les-Bains  Montauban  Avignon  Albi  Mont-de-Marsan  Nîmes  Nice  Auch  Montpellier  Toulouse  Pau  Marseille  Tarbes  Carcassonne  Toulon  Foix  Bastia  Perpignan  Ajaccio  Basse-Terre  Fort-de-France  Cayenne  Mamoudzou  Saint-Denis  

Question 13 : Ecrire des lignes de code permettant d'afficher les noms des départements français dans l'ordre alphabétique, sans modifier la table pref :

In [23]:
def cle_dep_nom(d):
    """
    Retourne la valeur associée à la clé 'dep_nom' dans le dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'dep_nom')
    - Sortie : (chaîne de caractères)
    """
    return d['dep_nom'].lower()

pref2 = sorted(pref, key = cle_dep_nom)

for k in range(len(pref2)):
    print(pref2[k]['dep_nom'], end = '  ')
Ain  Aisne  Allier  Alpes-de-Haute-Provence  Alpes-Maritimes  Ardennes  Ardèche  Ariège  Aube  Aude  Aveyron  Bas-Rhin  Bouches-du-Rhône  Calvados  Cantal  Charente  Charente-Maritime  Cher  Corrèze  Corse-du-Sud  Creuse  Côte-d'Or  Côtes-d'Armor  Deux-Sèvres  Dordogne  Doubs  Drôme  Essonne  Eure  Eure-et-Loir  Finistère  Gard  Gers  Gironde  Guadeloupe  Guyane  Haut-Rhin  Haute-Corse  Haute-Garonne  Haute-Loire  Haute-Marne  Haute-Savoie  Haute-Saône  Haute-Vienne  Hautes-Alpes  Hautes-Pyrénées  Hauts-de-Seine  Hérault  Ille-et-Vilaine  Indre  Indre-et-Loire  Isère  Jura  Landes  Loir-et-Cher  Loire  Loire-Atlantique  Loiret  Lot  Lot-et-Garonne  Lozère  Maine-et-Loire  Manche  Marne  Martinique  Mayenne  Mayotte  Meurthe-et-Moselle  Meuse  Morbihan  Moselle  Nièvre  Nord  Oise  Orne  Paris  Pas-de-Calais  Puy-de-Dôme  Pyrénées-Atlantiques  Pyrénées-Orientales  Rhône  Réunion  Sarthe  Savoie  Saône-et-Loire  Seine-et-Marne  Seine-Maritime  Seine-Saint-Denis  Somme  Tarn  Tarn-et-Garonne  Territoire de Belfort  Val-d'Oise  Val-de-Marne  Var  Vaucluse  Vendée  Vienne  Vosges  Yonne  Yvelines  

Question 14 : Ecrire des lignes de code permettant d'afficher les préfectures dans l'ordre alphabétique, sans modifier la table pref :

In [24]:
def cle_ville(d):
    """
    Retourne la valeur associée à la clé 'ville' dans le dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'ville')
    - Sortie : (chaîne de caractères)
    """
    return d['ville'].lower()

pref2 = sorted(pref, key = cle_ville)

for k in range(len(pref2)):
    print(pref2[k]['ville'], end = '  ')
Agen  Ajaccio  Albi  Alençon  Amiens  Angers  Angoulême  Annecy  Arras  Auch  Aurillac  Auxerre  Avignon  Bar-le-Duc  Basse-Terre  Bastia  Beauvais  Belfort  Besançon  Blois  Bobigny  Bordeaux  Bourg-en-Bresse  Bourges  Caen  Cahors  Carcassonne  Cayenne  Chambéry  Charleville-Mézières  Chartres  Chaumont  Châlons-en-Champagne  Châteauroux  Clermont-Ferrand  Colmar  Créteil  Digne-les-Bains  Dijon  Foix  Fort-de-France  Gap  Grenoble  Guéret  La Roche-sur-Yon  La Rochelle  Laon  Laval  Le Mans  Le Puy-en-Velay  Lille  Limoges  Lons-le-Saunier  Lyon  Mamoudzou  Marseille  Melun  Mende  Metz  Mont-de-Marsan  Montauban  Montpellier  Moulins  Mâcon  Nancy  Nanterre  Nantes  Nevers  Nice  Niort  Nîmes  Orléans  Paris  Pau  Perpignan  Poitiers  Pontoise  Privas  Périgueux  Quimper  Rennes  Rodez  Rouen  Saint-Brieuc  Saint-Denis  Saint-Lô  Saint-Étienne  Strasbourg  Tarbes  Toulon  Toulouse  Tours  Troyes  Tulle  Valence  Vannes  Versailles  Vesoul  Épinal  Évreux  Évry  
On rencontre ici une difficulté : les villes dont la première lettre porte un accent ne sont pas classées correctement. La raison est que le classement des chaînes de caractère se fait suivant l'ordre lexicographique, dans lequel les caractères sont classés en fonction de leur code Unicode : d'abord les majuscules, puis les minuscules, puis les lettres accentuées... Une façon de contourner le problème est de retirer les accents et les majuscules dans la chaîne retournée par cle_ville.
In [25]:
def ascii(phrase):
    """
    Transforme une chaîne de caractères en enlevant majuscules et accents.
    - Entrée : phrase (chaîne de caractères)
    - Sortie : nouvelle_phrase (chaîne de caractères)
    """
    if type(phrase) != str:
        raise TypeError('l\'argument doit être une chaîne de caractères')
    nouvelle_phrase = ''
    for lettre in phrase:
        lettre = lettre.lower()
        if lettre in 'àâä':
            nouvelle_phrase += 'a'
        elif lettre in 'éèêë':
            nouvelle_phrase += 'e'
        elif lettre in 'îï':
            nouvelle_phrase += 'i'
        elif lettre in 'ôö':
            nouvelle_phrase += 'o'
        elif lettre in 'ùûü':
            nouvelle_phrase += 'u'
        elif lettre == 'ÿ':
            nouvelle_phrase += 'y'
        elif lettre == 'ç':
            nouvelle_phrase += 'c'
        elif lettre == 'æ':
            nouvelle_phrase += 'ae'
        elif lettre == 'œ':
            nouvelle_phrase += 'oe'
        else:
            nouvelle_phrase += lettre
    return nouvelle_phrase

def cle_ville(d):
    """
    Retourne la valeur associée à la clé 'ville' dans le dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'ville')
    - Sortie : (chaîne de caractères)
    """
    return ascii(d['ville'])

pref2 = sorted(pref, key = cle_ville)

for k in range(len(pref2)):
    print(pref2[k]['ville'], end = '  ')
Agen  Ajaccio  Albi  Alençon  Amiens  Angers  Angoulême  Annecy  Arras  Auch  Aurillac  Auxerre  Avignon  Bar-le-Duc  Basse-Terre  Bastia  Beauvais  Belfort  Besançon  Blois  Bobigny  Bordeaux  Bourg-en-Bresse  Bourges  Caen  Cahors  Carcassonne  Cayenne  Châlons-en-Champagne  Chambéry  Charleville-Mézières  Chartres  Châteauroux  Chaumont  Clermont-Ferrand  Colmar  Créteil  Digne-les-Bains  Dijon  Épinal  Évreux  Évry  Foix  Fort-de-France  Gap  Grenoble  Guéret  La Roche-sur-Yon  La Rochelle  Laon  Laval  Le Mans  Le Puy-en-Velay  Lille  Limoges  Lons-le-Saunier  Lyon  Mâcon  Mamoudzou  Marseille  Melun  Mende  Metz  Mont-de-Marsan  Montauban  Montpellier  Moulins  Nancy  Nanterre  Nantes  Nevers  Nice  Nîmes  Niort  Orléans  Paris  Pau  Périgueux  Perpignan  Poitiers  Pontoise  Privas  Quimper  Rennes  Rodez  Rouen  Saint-Brieuc  Saint-Denis  Saint-Étienne  Saint-Lô  Strasbourg  Tarbes  Toulon  Toulouse  Tours  Troyes  Tulle  Valence  Vannes  Versailles  Vesoul  

Partie D - Fusion de deux tables

Le fichier population.csv (créé à partir de données récoltées sur le site de l'INSEE) contient la population estimée de chaque département français au 1er janvier 2020, ainsi que la répartition de cette population par tranche d'âge :

Tranche
Population
A
0 à 19 ans
B
20 à 39 ans
C
40 à 59 ans
D
60 à 74 ans
E
plus de 75 ans

Question 15 : Ecrire des lignes de code permettant d'importer les données du fichier population.csv dans un tableau pop composé de dictionnaires. Les populations seront stockées sous forme d'entiers.

In [26]:
pop = importer_donnees('population.csv')

for k in range(len(pop)):
    pop[k]['popA'] = int(pop[k]['popA'])
    pop[k]['popB'] = int(pop[k]['popB'])
    pop[k]['popC'] = int(pop[k]['popC'])
    pop[k]['popD'] = int(pop[k]['popD'])
    pop[k]['popE'] = int(pop[k]['popE'])
    pop[k]['pop'] = int(pop[k]['pop'])

Puisque les deux tables pref et pop possèdent en commun le champ dep, il semble intéressant de pouvoir créer une table unique regroupant les données présentes dans chacune des deux tables. On parle de jointure des deux tables.

On commence par créer une fonction fusion dont le rôle est de fusionner deux dictionnaires en un seul :

In [27]:
def fusion(d1, d2):
    """
    Fusionne deux dictionnaires
    - Entrées : d1 (dictionnaire contenant les clés 'dep', 'dep_nom', 'ville', 'lat' et 'long')
                d2 (dictionnaire contenant les clés 'dep', 'popA', 'popB', 'popC', 'popD', 'popE' et 'pop')
    - Sortie : (dictionnaire unique contenant toutes les clés citées précédemment)
    """
    return {'dep' : d1['dep'], 'dep_nom' : d1['dep_nom'], 'ville' : d1['ville'], 'lat' : d1['lat'], 'long' : d1['long'],
           'popA' : d2['popA'], 'popB' : d2['popB'], 'popC' : d2['popC'], 'popD' : d2['popD'], 'popE' : d2['popE'],
           'pop' : d2['pop']}

La jointure des deux tables d'effectue alors à l'aide d'une double boucle :

In [28]:
table = []
for d1 in pref:
    for d2 in pop:
        if d1['dep'] == d2['dep']:
            table.append(fusion(d1, d2))

Voici les cinq premiers éléments de la table ainsi obtenue :

In [29]:
for k in range(5):
    print(table[k])
{'dep': '1', 'dep_nom': 'Ain', 'ville': 'Bourg-en-Bresse', 'lat': 46.2025, 'long': 5.221944444444444, 'popA': 167666, 'popB': 151084, 'popC': 179469, 'popD': 104453, 'popE': 54283, 'pop': 656955}
{'dep': '2', 'dep_nom': 'Aisne', 'ville': 'Laon', 'lat': 49.562222222222225, 'long': 3.6225, 'popA': 129852, 'popB': 114042, 'popC': 135164, 'popD': 98046, 'popE': 48946, 'pop': 526050}
{'dep': '3', 'dep_nom': 'Allier', 'ville': 'Moulins', 'lat': 46.568333333333335, 'long': 3.334444444444444, 'popA': 66659, 'popB': 61490, 'popC': 85304, 'popD': 72079, 'popE': 45783, 'pop': 331315}
{'dep': '4', 'dep_nom': 'Alpes-de-Haute-Provence', 'ville': 'Digne-les-Bains', 'lat': 44.09222222222222, 'long': 6.238055555555555, 'popA': 34281, 'popB': 30814, 'popC': 43423, 'popD': 35681, 'popE': 20998, 'pop': 165197}
{'dep': '5', 'dep_nom': 'Hautes-Alpes', 'ville': 'Gap', 'lat': 44.5575, 'long': 6.076111111111111, 'popA': 30280, 'popB': 27715, 'popC': 37829, 'popD': 29047, 'popE': 16885, 'pop': 141756}
On constate que chaque élément de table est un dictionnaire possédant à la fois les clés issues des enregistrements du tableau pref et du tableau pop.

Il est enfin possible d'enregistrer la nouvelle table dans un ficher CSV, grâce à la fonction suivante :

In [30]:
import csv

def exporter_donnees(nom_de_fichier, tab):
    """
    Exporte les données de tab vers un fichier CSV
    - Entrée : nom_de_fichier (chaîne de caractères correspondant à un nom de fichier CSV), tab (tableau de dictionnaires)
    - Effet de bord : écriture dans un fichier texte
    Attention : le fichier texte est écrasé, son contenu précédent est effacé
    """
    with open(nom_de_fichier, 'w', encoding = 'utf-8') as fichier:
        donnees = csv.DictWriter(fichier, ['dep', 'dep_nom', 'ville', 'lat', 'long', 'popA', 'popB', 'popC',
                                           'popD', 'popE', 'pop'], delimiter = ',')
        donnees.writeheader() # Ecriture des clés sur la première ligne du fichier CSV
        donnees.writerows(tab) # Ecriture des enregistrements à partir de la deuxième ligne du fichier CSV
In [31]:
exporter_donnees('nouveau.csv', table)

Ce que vous devez savoir

  • Importer une table de données depuis un fichier CSV, et stocker le résultat sous forme de tableau de dictionnaires.
  • Valider les données, c'est-à-dire modifier leur type pour les rendre utilisables.
  • Afficher des données sélectionnées dans une table.
  • Compter des données sélectionnées dans une table.
  • Définir une fonction de tri utilisable comme argument de la commande .sort() ou de la fonction sorted.
  • Utiliser le paramètre reverse pour effectuer un tri dans l'ordre décroissant.
  • Choisir entre la commande .sort() et la fonction sorted en fonction du contexte.
  • Fusionner les données contenues dans deux tables.
  • Exporter les données dans un fichier CSV.

Exercices bilan

Exercice 1

Ecrire des lignes de code permettant de calculer la population française totale estimée au 1er janvier 2020.

In [32]:
population_totale = 0
for k in range(len(table)):
    population_totale += table[k]['pop']
print('L\'INSEE estime que la population française totale au 1er janvier 2020 est de', population_totale, 'hab.')
L'INSEE estime que la population française totale au 1er janvier 2020 est de 67063703 hab.

Ecrire des lignes de code permettant d'afficher la liste des dix départements les plus peuplés et leur population, par ordre décroissant de population.

In [33]:
def cle_pop(d):
    """
    Retourne la valeur associée à la clé 'pop' dans le dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'pop')
    - Sortie : (entier)
    """
    return d['pop']

table2 = sorted(table, key = cle_pop, reverse = True)

for k in range(10):
    print(table2[k]['dep_nom'], ':', table2[k]['pop'])
Nord : 2588988
Paris : 2148271
Bouches-du-Rhône : 2034469
Rhône : 1876051
Seine-Saint-Denis : 1670149
Gironde : 1633440
Hauts-de-Seine : 1613762
Pas-de-Calais : 1452778
Yvelines : 1448625
Loire-Atlantique : 1437137

Ecrire des lignes de code permettant d'afficher la liste des dix départements dont la proportion de moins de 20 ans est la plus forte, puis la liste des dix départements pour lesquels cette proportion est la plus faible.

In [34]:
def cle_taux_jeunes(d):
    """
    Retourne le taux de moins de 20 ans calculé avec les données du dictionnaire d
    - Entrée : d (dictionnaire contenant au moins les clés 'popA' et 'pop')
    - Sortie : (nombre flottant)
    """
    return d['popA'] / d['pop']

table2 = sorted(table, key = cle_taux_jeunes, reverse = True)
In [35]:
for k in range(10):
    print(table2[k]['dep_nom'], ':', round(table2[k]['popA'] / table2[k]['pop'] * 100, 2), '%')
Mayotte : 53.76 %
Guyane : 41.52 %
Réunion : 29.79 %
Seine-Saint-Denis : 29.04 %
Val-d'Oise : 28.64 %
Seine-et-Marne : 27.54 %
Essonne : 27.31 %
Yvelines : 26.63 %
Nord : 26.09 %
Oise : 26.03 %
In [36]:
for k in range(len(table)-1, len(table)-11, -1):
    print(table2[k]['dep_nom'], ':', round(table2[k]['popA'] / table2[k]['pop'] * 100, 2), '%')
Creuse : 17.86 %
Lot : 18.4 %
Cantal : 18.61 %
Dordogne : 18.71 %
Paris : 18.93 %
Nièvre : 19.13 %
Corse-du-Sud : 19.47 %
Hautes-Pyrénées : 19.77 %
Gers : 19.78 %
Indre : 19.78 %

Ecrire des lignes de code permettant d'afficher la liste des dix départements dont la proportion de plus de 75 ans est la plus forte, puis la liste des dix départements pour lesquels cette proportion est la plus faible.

In [37]:
def cle_taux_seniors(d):
    """
    Retourne le taux de plus de 75 ans calculé avec les données du dictionnaire d
    - Entrée : d (dictionnaire contenant au moins les clés 'popE' et 'pop')
    - Sortie : (nombre flottant)
    """
    return d['popE'] / d['pop']

table2 = sorted(table, key = cle_taux_seniors, reverse = True)
In [38]:
for k in range(10):
    print(table2[k]['dep_nom'], ':', round(table2[k]['popE'] / table2[k]['pop'] * 100, 2), '%')
Lot : 14.89 %
Creuse : 14.68 %
Nièvre : 14.4 %
Dordogne : 14.16 %
Cantal : 14.14 %
Gers : 14.02 %
Indre : 14.0 %
Aveyron : 13.97 %
Allier : 13.82 %
Corrèze : 13.62 %
In [39]:
for k in range(len(table)-1, len(table)-11, -1):
    print(table2[k]['dep_nom'], ':', round(table2[k]['popE'] / table2[k]['pop'] * 100, 2), '%')
Mayotte : 0.87 %
Guyane : 2.1 %
Seine-Saint-Denis : 5.01 %
Réunion : 5.21 %
Val-d'Oise : 6.01 %
Seine-et-Marne : 6.46 %
Essonne : 7.12 %
Val-de-Marne : 7.13 %
Oise : 7.41 %
Nord : 7.58 %

Exercice 2

Le fichier emissions_CO2.csv (créé à partir de données récoltées sur le site de la Banque mondiale) contient les quantités de CO2, en tonnes par habitant, émises par chaque pays de l'Union Européenne, pour les années 2000 et 2010.

Ecrire des lignes de code permettant d'importer les données du fichier. Les quantités de CO2 émises seront stockées sous forme de nombre flottant.

In [40]:
co2 = importer_donnees('emissions_CO2.csv')

for k in range(len(co2)):
    co2[k]['em_2000'] = float(co2[k]['em_2000'])
    co2[k]['em_2010'] = float(co2[k]['em_2010'])

Ecrire des lignes de code permettant d'afficher la liste des pays de l'UE qui ont diminué leurs émissions de CO2 par habitant entre 2000 et 2010.

In [41]:
for k in range(len(co2)):
    if co2[k]['em_2010'] < co2[k]['em_2000']:
        print(co2[k]['nom_pays'], end = '  ')
Belgique  Chypre  République tchèque  Allemagne  Danemark  Espagne  France  Grèce  Hongrie  Irlande  Italie  Portugal  Roumanie  Suède  

Ecrire des lignes de code permettant d'afficher le nom des cinq pays qui émettent le plus de CO2 par habitant en 2010, puis le nom des cinq pays qui en émettent le moins.

In [42]:
def cle_emission_2010(d):
    """
    Retourne la valeur associée à la clé 'em_2010' dans le dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'em_2010')
    - Sortie : (nombre flottant)
    """
    return d['em_2010']

table = sorted(co2, key = cle_emission_2010, reverse = True)
In [43]:
for k in range(5):
    print(table[k]['nom_pays'], ':', round(table[k]['em_2010'], 2), 't/hab.')
Luxembourg : 21.64 t/hab.
Estonie : 13.6 t/hab.
Finlande : 11.58 t/hab.
Pays-Bas : 11.02 t/hab.
République tchèque : 10.65 t/hab.
In [44]:
for k in range(len(table)-1, len(table)-6, -1):
    print(table[k]['nom_pays'], ':', round(table[k]['em_2010'], 2), 't/hab.')
Lettonie : 3.85 t/hab.
Roumanie : 3.92 t/hab.
Lituanie : 4.35 t/hab.
Portugal : 4.55 t/hab.
Croatie : 4.7 t/hab.

Ecrire des lignes de code permettant d'afficher, pour chaque pays, le taux d'évolution de ses émissions de CO2 par habitant entre 2000 et 2010. Les pays seront classés de celui qui a le taux d'évolution le plus négatif à celui qui a le taux d'évolution le plus positif.

On rappelle qu'un taux d'évolution se calcule avec la formule suivante : taux_evolution = (valeur_finale - valeur_initiale) / valeur_initiale.

In [45]:
for k in range(len(table)):
    taux_evolution = (table[k]['em_2010'] - table[k]['em_2000']) / table[k]['em_2000']
    table[k]['taux_evol'] = taux_evolution
In [46]:
def cle_taux_evolution(d):
    """
    Retourne le taux d'évolution des émissions de CO2 entre 2000 et 2010 calculé avec les données du dictionnaire d
    - Entrée : d (dictionnaire contenant au moins la clé 'taux_evol')
    - Sortie : (nombre flottant)
    """
    return d['taux_evol']

table = sorted(co2, key = cle_taux_evolution)
In [47]:
for k in range(len(table)):
    print(table[k]['nom_pays'], ':', round(table[k]['taux_evol'] * 100, 1), '%')
Portugal : -25.3 %
Espagne : -19.9 %
Irlande : -18.9 %
Italie : -13.6 %
Danemark : -12.5 %
République tchèque : -11.8 %
Grèce : -11.1 %
Belgique : -9.4 %
France : -8.7 %
Hongrie : -8.1 %
Allemagne : -8.1 %
Chypre : -5.7 %
Roumanie : -2.9 %
Suède : -0.3 %
Slovaquie : 0.9 %
Pays-Bas : 1.1 %
Slovénie : 3.4 %
Autriche : 3.8 %
Pologne : 6.3 %
Croatie : 8.5 %
Bulgarie : 12.0 %
Finlande : 14.3 %
Luxembourg : 14.6 %
Malte : 16.7 %
Lituanie : 25.1 %
Estonie : 27.9 %
Lettonie : 43.5 %

Ecrire des lignes de code permettant de stocker dans un nouveau fichier CSV la liste des pays de l'UE et leur taux d'évolution des émissions de CO2 par habitant.

In [48]:
import csv

def exporter_donnees(nom_de_fichier, tab):
    """
    Exporte les données de tab vers un fichier CSV
    - Entrée : nom_de_fichier (chaîne de caractères correspondant à un nom de fichier CSV), tab (tableau de dictionnaires)
    - Effet de bord : écriture dans un fichier texte
    Attention : le fichier texte est écrasé, son contenu précédent est effacé
    """
    with open(nom_de_fichier, 'w', encoding = 'utf-8') as fichier:
        donnees = csv.DictWriter(fichier, ['nom_pays', 'em_2000', 'em_2010', 'taux_evol'], delimiter = ',')
        donnees.writeheader() # Ecriture des clés sur la première ligne du fichier CSV
        donnees.writerows(tab) # Ecriture des enregistrements à partir de la deuxième ligne du fichier CSV
In [49]:
exporter_donnees('nouveau_CO2.csv', table)