Importer des données tabulaires

De grandes quantités de données sont librement accessibles, notamment sur le site data.gouv.fr. On peut les exploiter en classe.

Pour importer ces données comme des tableaux, on dispose du module csv disponible dans la bibliothèque standard: tout tableur peut importer et exporter des données dans ce format.

Prenons par exemple la liste intégrale des adresses des Bouches-du-Rhône, sous la forme d’un fichier CSV téléchargeable depuis le site d’OpenStreetMap.

Ce fichier est compressé au format bzip2: il n’y a pas forcément de quoi ouvrir cette archive sur votre ordinateur… sauf que Python sait déjà gérer ce format, avec le module bz2.

Jouons un peu:

   1 import bz2
   2 with bz2.open('BAN_odbl_13-csv.bz2') as f:
   3         for ligne in f.readlines(1000): # lit au plus 1000 octets
   4                 print(ligne)

Bref, bz2.open, c’est comme open, sauf que ça décompresse à la volée.

En regardant le contenu, on voit que :

On est prêts à utiliser le module csv : on fabrique un objet itérable, sur lequel on peut faire une boucle for.

   1 import csv
   2 with bz2.open('BAN_odbl_13-csv.bz2') as f:
   3         lecteur = csv.reader(f)
   4         for ligne in lecteur:
   5                 print(ligne)

Ça râle, parce que par défaut, un fichier bz2 est lu en mode binaire (on obtient des séquences d’octets) alors que le module csv veut du texte (des chaînes de caractéres).

Comme dit dans la documentation de bz2, il faut ajouter l’argument 'rt':

   1 import csv
   2 with bz2.open('BAN_odbl_13-csv.bz2','rt') as f:
   3         lecteur = csv.reader(f)
   4         for ligne in lecteur:
   5                 print(ligne)

C’est long ! Si on veut seulement lire ligne à ligne, on peut utiliser la primitive next qui renvoie la première entrée d’un itérateur, et passe à la suivante.

   1 import csv
   2 with bz2.open('BAN_odbl_13-csv.bz2','rt') as f:
   3         lecteur = csv.reader(f)
   4         for i in range(10):
   5                 print(next(lecteur))

Mais ça représente un volume de données raisonnable pour un ordinateur d’aujourd’hui : on peut tout charger en mémoire pour le traiter.

Avec tout ce qu’on a vu jusque là, on obtient le début programme :

   1 def lit_csv(f):
   2         """Lit un objet fichier `f` au format CSV, et retourne le couple `(entête,lignes)`:
   3  * `entête` est la première ligne ;
   4  * `lignes` est le tuple des lignes suivantes.
   5         """
   6         import csv
   7         lecteur = csv.reader(f)
   8         entête = next(lecteur)
   9         lignes = tuple(lecteur)
  10         return entête, lignes
  11 
  12 def ligne_avec_entête(entête,ligne):
  13         "Renvoie une chaîne qui représente les valeurs de la `ligne`."
  14         entrées = []
  15         for i in range(len(entête)):
  16                 entrée = entête[i] + ": " + ligne[i]
  17                 entrées = entrées + [entrée]
  18         return " | ".join(entrées)
  19 
  20 if __name__ == '__main__':
  21         import bz2
  22         with bz2.open('BAN_odbl_13-csv.bz2','rt') as f:
  23                 entête, lignes = lit_csv(f)
  24         print("Les colonnes du fichier sont :", ", ".join(entête))
  25         print("Il y a",len(lignes),"entrées")
  26         print("Première ligne :")
  27         print(ligne_avec_entête(entête,lignes[0]))
  28         print("Dernière ligne :")
  29         print(ligne_avec_entête(entête,lignes[-1]))

À vous de jouer. Par exemple, définissez une fonction qui renvoie la liste de tous les numéros d’une rue donnée dans une ville donnée. Ou la liste de toutes les rues d’une ville donnée.

EnsInfo: Importer des données de tableur (last edited 2019-01-22 23:25:32 by LionelVaux)