Aller au contenu

Données en table (format csv) : filtres, tris

Données en exemple pour le TP

On va utiliser les fichiers villes.csv et pays.csv.

Lire le format csv en python

import csv

fichier = open("pays.csv")
pays = list(csv.DictReader(fichier,delimiter=";"))

Ensuite on peut tester dans la console:

>>> pays[0]
{'ISO': 'AD', 'Name': 'Andorra', 'Capital_Id': '3041563', 'Area': '468', 'Population': '84000', 'Continent': 'EU', 'Currency_Code': 'EUR', 'Currency_Name': 'Euro'}

À faire

Ouvrez Thonny et enregistrer le fichier python au même endroit que les fichiers csv.
Copiez et exécuter les lignes au dessus :

  • quel est le type de pays ?
  • quel est le type de pays[0] ? C'est un type très proche de dict qu'on pourra utiliser comme si c'était un dictionnaire

Chaque p-uplet de données est donc représenté par un dictionnaire en python, où les clés sont les noms des descripteurs qui sont les mêmes pour chaque p-uplet, et les valeurs associées sont celles de la ligne de la table correspondante.

Attention

Le type des valeurs en python si on lit le fichier comme ça sera toujours string. Si la valeur est en fait un nombre et qu'on veut faire des calculs ou des comparaisons dessus, il faudra la convertir avec int() ou float().

Pour parcourir toute la table, on peut faire une boucle for qui parcourt directement la liste des dictionnaires :

for p in pays:
    print(p)

On va maintenant pouvoir modifier cette boucle pour répondre à diverses questions sur les données.

Filtrer la table

En rajoutant un test if dans la boucle, on peut afficher seulement les lignes qui vérifient une proposition logique.

À faire

  • Combien de pays ont pour monnaie le dinar ? Il s'agit de n'afficher que les lignes où la valeur du descripteur "Currency_Name" vaut "Dinar".

  • Quels sont les pays d'Amérique du Sud dont la monnaie s'appelle "Dollar" ? Il faut faire la conjonction de deux conditions dans le if avec and. Le code du continent pour l'amérique du sud est "SA".

  • Quels sont les pays qui ont moins de 1000 habitants ? Attention, il faut convertir la valeur de Population en int pour pouvoir la comparer.

Aggrégation de résultats

De la même manière que quand on cherchait le minimum ou la somme des éléments d'un tableau, on peut créer une variable avant la boucle et la mettre à jour pour calculer quelque chose sur la table.

À faire

  • Quelle est la population mondiale totale d'après ces données ? (encore une fois, convertir la Population des pays en int pour les additionner)

  • Quel est le pays qui a le plus petit nombre d'habitants au km² ? Et de combien est cette densité ?

Trier la table

Comme dans un tableur, on peut vouloir trier la table dans un certain ordre.

En python on peut trier une liste de manière efficace avec la méthode .sort(), mais nos données sont dans une liste de dictionnaire et les dictionnaires ne sont pas directement comparables donc on obtient une erreur :

>>> pays.sort()
Traceback (most recent call last):
  File "<pyshell>", line 1, in <module>
TypeError: '<' not supported between instances of 'dict' and 'dict'

Pour résoudre ce problème, on peut ajouter un paramètre nommé key à la méthode sort qui doit être une fonction qui va convertir les éléments du dictionnaire en quelque chose de comparable.

Par exemple on peut créer une fonction population qui transforme un p-uplet en la valeur de sa population de type int, ce qui permet de trier par population croissante.

def population(p):
    return int(p["Population"])

pays.sort(key=population)

À Faire

  • Quel est le 10e plus grand pays au monde ? (Indice : pour trier par ordre décroissant, on peut donner comme key une fonction qui renvoie l'opposé de la valeur)

Si on veut trier par plusieurs critères (par exemple par ordre alphabétique de monnaie, et si la monnaie est égale par ordre alphabétique du nom de pays) on peut renvoyer un tuple :

def monnaie_puis_nom(p):
    return (p["Currency_Name"],p["Name"])

pays.sort(key=monnaie_puis_nom)

À faire

  • Quel est le premier pays qu'on obtient si on trie d'abord par la longueur du nom du pays, et à longueur égale par population croissante ?

  • (tri + filtre) Quel est le 4e plus grand pays de la zone euro ?

Sauvegarder une nouvelle table dans un fichier csv

On peut utiliser DictWriter pour écrire un nouveau fichier csv.

Par exemple, pour écrire un fichier csv des pays de la zone euro :

pays_euro = []

for p in pays:
    if p["Currency_Name"]=="Euro":
        pays_euro.append(p)

fichier_out = open("euro.csv","w") # "w" pour l'ouverture en écriture (write)
noms_descripteurs = pays_euro[0].keys() # .keys() donne les clés d'un dictionnaire, donc les descripteurs ici
writer = csv.DictWriter(fichier_out,noms_descripteurs)
writer.writeheader() # écrire les noms des descripteurs
writer.writerows(pays_euro) # écrire toutes les lignes de la liste pays_euro
fichier_out.close() # fermer le fichier

À faire

  • Créez un fichier csv qui liste les pays du continent asiatique.

Fusion de tables

On n'a pas encore utilisé le fichier ̀villes.csv`, qui recense des données sur 24338 villes dans le monde.

La colonne Country_ISO correspond à la colonne ISO du fichier pays.csv, et la colonne Capital_Id de pays.csv correspond à la colonne Id de villes.csv.

On veut parfois faire des requêtes sur plusieurs tables à la fois, par exemple :

  • Quelles sont les 3 villes au monde avec plus de 12 millions d'habitants qui ne sont pas des capitales ?

Pour y répondre, on ne sait pas dans la table villes.csv si une ville est une capitale. Il faut donc:

Pour chaque ville:
    Si elle a plus de 12 millions d'habitants:
        est_capitale = False
        Pour chaque pays:
            Si la capitale du pays est la ville actuelle:
                est_capitale = True
        Si est_capitale est True:
            afficher la ville

Info

Ces opérations sur les tables (en particulier les jointures) seront plus faciles et efficaces à réaliser si on les stocke sous forme de base de données. Le langage SQL sert alors à écrire des requêtes qui sont exécutées par un logiciel spécialisé : un système de gestion de base de données (SGBD).

Tout cela est au programme de NSI de Terminale.

Questions supplémentaires

  • Quelle est la ville d'Inde la plus au sud ?

  • Quelle est la ville de la liste qui a le nombre d'habitants le plus proche de Grenoble ?

  • Pour chaque continent, quelle est la ville qui a le nombre d'habitants le plus proche de Grenoble ?

  • Quelle est la ville la plus proche du point de la Terre opposé à Grenoble ?

  • (Pour occuper si vous avez trop de temps :) On veut aller à Shanghai à vélo en s'arrêtant chaque soir dans une ville. Avec quelle longueur d'étape maximale en km peut-on y arriver ?