5 Chargement et sauvegarde de données
Pour explorer des données et/ou réaliser des analyses statistiques ou économétriques, il est important de savoir importer et exporter des données.
Avant toute chose, il convient d’évoquer la notion de répertoire courant (working directory). En informatique, le répertroire courant d’un processus désigne un répertoire du système de fichier associé à ce processus.
Lorsqu’on lance Jupyter, une arborescence nous est proposée, et nous navigons à l’interieur de celle-ci pour créer ou ouvrir un notebook. Le répertoire contenant le notebook est le répertoire courant. Lorsqu’on indiquera à Python d’importer des données (ou d’exporter des objets), l’origine (ou la destination) sera indiquée relativement au répertoire courant, à moins d’avoir recours à des chemins absolus (c’est-à-dire un chemin d’accès à partir de la racine /
).
Si on lance un programme Python depuis un terminal, le répertoire courant est le répertoire dans lequel on se trouve dans le terminal au moment de lancer le programme.
Pour afficher dans Python le répertoire courant, on peut utiliser le code suivant :
import os
cwd = os.getcwd()
print(cwd)
## /Users/ewengallic/Dropbox/Universite_Aix_Marseille/Magistere_2_Programming_for_big_data/Cours/chapters/python/Python_pour_economistes
La fonction listdir()
de la librairie os
est très pratique : elle permet de lister tous les documents et répertoires contenus dans le répertoire couant, ou dans n’importe quel répertoire si le paramètre path
renseigne le chemin (absolu ou relatif). Après avoir importé la fonction (from os import getcwd
), on peut l’appeler : os.listdir()
.
5.1 Charger des données
En fonction du format d’enregistrement des données, les techniques d’importation de données diffèrent.
pandas
.
5.1.1 Fichiers textes
Lorsque les données sont présentes dans un fichier texte (ASCII), Python propose d’utiliser la fonction open()
.
La syntaxe (simplifiée) de la fonction open()
est la suivante :
open(file, mode='r', buffering=-1,
encoding=None, errors=None, newline=None)
Voici à quoi correspondent les paramètres (il en existe d’autres) :
file
: une chaîne de caractères indiquant le chemin et le nom du fichier à ouvrir ;mode
: spécifie la manière par laquelle le fichier est ouvert (c.f. juste après pour les valeurs possibles) ;buffering
: spécifie à l’aide d’un entier le comportement à adopter pour la mise en mémoire tampon (1 pour mettre en mémoire par ligne ; un entier \(>1\) pour indiquer la taille en octets des morceaux à charger en mémoire tampon) ;encoding
: spécifie l’encodage du fichier ;errors
: spécifie la manière de gérer les erreurs d’encodage et de décodage (e.g.,strict
retourne une erreur d’exception,ignore
permet d’ignorer les erreurs,replace
de les remplacer,backslashreplace
de remplacer les données mal formées par des séquences d’échappement) ;newline
: contrôle la fin des lignes (\n
,\r
, etc.).
Valeur | Description |
---|---|
r |
Ouverture pour lire (défaut) |
w |
Ouverture pour écrire |
x |
Ouverture pour créer un document, échoue si le fichier existe déjà |
a |
Ouverture pour écrire, en venant ajouter à la fin du fichier si celui-ci existe déjà |
+ |
Ouverture pour mise à jour (lecture et écriture) |
b |
À ajouter à un mode d’ouverture pour les fichiers binaires (rb ou wb ) |
t |
Mode texte (décodage automatique des octets en Unicode). Par défaut si non spécifié (s’ajoute au mode, comme b ) |
Il est important de bien penser à fermer le fichier une fois qu’on a terminé de l’utiliser. Pour ce faire, on utilise la méthode close()
.
Dans le dossier fichiers_exemples
se trouve un fichier appelé fichier_texte.txt
qui contient trois lignes de texte. Ouvrons ce fichier, et utilisons la méthode .read()
pour afficher son contenu :
path = "./fichiers_exemples/fichier_texte.txt"
# Ouverture en mode lecture (par défaut)
mon_fichier = open(path, mode = "r")
print(mon_fichier.read())
## Bonjour, je suis un fichier au format txt.
## Je contiens plusieurs lignes, l'idée étant de montrer comment fonctionne l'importation d'un tel fichier dans Python.
## Trois lignes devraient suffir.
mon_fichier.close()
Une pratique courante en Python est d’ouvrir un fichier dans un bloc with
. La raison de ce choix est qu’un fichier ouvert dans un tel bloc est automatiquement refermé à la fin du bloc.
La syntaxe est la suivante :
# Ouverture en mode lecture (par défaut)
with open(path, "r") as mon_fichier:
donnees = fonction_pour_recuperer_donnees_depuis_mon_fichier()
Par exemple, pour récupérer chaque ligne comme un élément d’une liste, on peut utiliser une boucle parcourant chaque ligne du fichier. À chaque itération, on récupère la ligne :
# Ouverture en mode lecture (par défaut)
with open(path, "r") as mon_fichier:
donnees = [x for x in mon_fichier]
print(donnees)
## ['Bonjour, je suis un fichier au format txt.\n', "Je contiens plusieurs lignes, l'idée étant de montrer comment fonctionne l'importation d'un tel fichier dans Python.\n", 'Trois lignes devraient suffir.']
Note : à chaque itération, on peut appliquer la méthode strip()
, qui retourne la chaîne de caractère de la ligne, en retirant les éventuels caractères blancs en début de chaîne :
# Ouverture en mode lecture (par défaut)
with open(path, "r") as mon_fichier:
donnees = [x.strip() for x in mon_fichier]
print(donnees)
## ['Bonjour, je suis un fichier au format txt.', "Je contiens plusieurs lignes, l'idée étant de montrer comment fonctionne l'importation d'un tel fichier dans Python.", 'Trois lignes devraient suffir.']
On peut également utiliser la méthode readlines()
pour importer les lignes dans une liste :
with open(path, "r") as mon_fichier:
donnees = mon_fichier.readlines()
print(donnees)
## ['Bonjour, je suis un fichier au format txt.\n', "Je contiens plusieurs lignes, l'idée étant de montrer comment fonctionne l'importation d'un tel fichier dans Python.\n", 'Trois lignes devraient suffir.']
Il se peut parfois que l’encodage des caractères pose problème lors de l’importation. Dans ce cas, il peut être une bonne idée de changer la valeur du paramètre encoding
de la fonction open()
. Les encodages disponibles sont fonction de la locale. Les valeurs disponibles s’obtiennent à l’aide de la méthode suivante (code non exécuté dans ces notes) :
import locale
locale.locale_alias
5.1.1.1 Importation depuis internet
Pour importer un fichier texte depuis Internet, on peut utiliser des méthodes de la librairie urllib
:
import urllib
from urllib.request import urlopen
url = "http://egallic.fr/Enseignement/Python/fichiers_exemples/fichier_texte.txt"
with urllib.request.urlopen(url) as mon_fichier:
donnees = mon_fichier.read()
print(donnees)
## b"Bonjour, je suis un fichier au format txt.\nJe contiens plusieurs lignes, l'id\xc3\xa9e \xc3\xa9tant de montrer comment fonctionne l'importation d'un tel fichier dans Python.\nTrois lignes devraient suffir."
Comme on peut le constater, l’encodage des caractères pose souci ici. On peut appliquer la méthode decode()
:
print(donnees.decode())
## Bonjour, je suis un fichier au format txt.
## Je contiens plusieurs lignes, l'idée étant de montrer comment fonctionne l'importation d'un tel fichier dans Python.
## Trois lignes devraient suffir.
5.1.2 Fichiers CSV
Les fichier CSV (comma separated value) sont très répandus. De nombreuses bases de données exportent leurs données en CSV (e.g., Banque Mondiale, FAO, Eurostat, etc.). Pour les importer dans Python, on peut uiliser le module csv
.
À nouveau, on utilise la fonction open()
, avec les paramètres décrits dans la Section 5.1.1. Ensuite, on fait appel à la méthode reader()
du module csv
:
import csv
with open('./fichiers_exemples/fichier_csv.csv') as mon_fichier:
mon_fichier_reader = csv.reader(mon_fichier, delimiter=',', quotechar='"')
donnees = [x for x in mon_fichier_reader]
print(donnees)
## [['nom', 'prénom', 'équipe'], ['Irving', ' "Kyrie"', ' "Celtics"'], ['James', ' "Lebron"', ' "Lakers"', ''], ['Curry', ' "Stephen"', ' "Golden State Warriors"']]
La méthode reader()
peut prendre plusieurs paramètres, décrits dans le Tableau 5.2.
Paramètre | Description |
---|---|
csvfile |
L’objet ouvert avec open() |
dialect |
Paramètre spécifiant le ‘dialect’ du fichier CSV (e.g., excel , excel-tab , unix ) |
delimiter |
Le caractère délimitant les champs (i.e., les valeurs des variables) |
quotechar |
Caractère utilisé pour entourer les champs contenant des caractères spéciaux |
escapechar |
Caractère d’échappement |
doublequote |
Contrôle comment les quotechar apparaissent à l’intérieur d’un champ : quand True , le caractère est doublé, ; quand False , le caractère d’échappement est utilisé en préfixe au quotechar |
lineterminator |
Chaîne de caractères utilisée pour terminer une ligne |
skipinitialspace |
Quand True , le caractère blanc situé juste après le caractère de séparation des champs est ignoré |
strict |
Quand True , retourne une erreur d’exception en cas de mauvais input de CSV |
On peut aussi importer un fichier CSV en tant que dictionnaire, à l’aide de la méthode csv.DictReader()
du module CSV :
import csv
chemin = "./fichiers_exemples/fichier_csv.csv"
with open(chemin) as mon_fichier:
mon_fichier_csv = csv.DictReader(mon_fichier)
donnees = [ligne for ligne in mon_fichier_csv]
print(donnees)
## [OrderedDict([('nom', 'Irving'), ('prénom', ' "Kyrie"'), ('équipe', ' "Celtics"')]), OrderedDict([('nom', 'James'), ('prénom', ' "Lebron"'), ('équipe', ' "Lakers"'), (None, [''])]), OrderedDict([('nom', 'Curry'), ('prénom', ' "Stephen"'), ('équipe', ' "Golden State Warriors"')])]
5.1.2.1 Importation depuis internet
Comme pour les fichiers txt
, on peut charger un fichier CSV hébergé sur Internet :
import csv
import urllib.request
import codecs
url = "http://egallic.fr/Enseignement/Python/fichiers_exemples/fichier_csv.csv"
with urllib.request.urlopen(url) as mon_fichier:
mon_fochier_csv = csv.reader(codecs.iterdecode(mon_fichier, 'utf-8'))
donnees = [ligne for ligne in mon_fochier_csv]
print(donnees)
## [['nom', 'prénom', 'équipe'], ['Irving', ' "Kyrie"', ' "Celtics"'], ['James', ' "Lebron"', ' "Lakers"', ''], ['Curry', ' "Stephen"', ' "Golden State Warriors"']]
5.1.3 Fichier JSON
Pour importer des fichiers au format JSON (JavaScript Object Notation), qui sont très utilisés dès lors qu’on communique avec une API, on peut utiliser la librairie json
, et sa méthode load()
:
import json
lien = './fichiers_exemples/tweets.json'
with open(lien) as mon_fichier_json:
data = json.load(mon_fichier_json)
Ensuite, on peut afficher le contenu importé à l’aide de la fonction pprint()
:
from pprint import pprint
pprint(data)
## {'created_at': 'Wed Sep 26 07:38:05 +0000 2018',
## 'id': 11,
## 'loc': [{'long': 5.3698}, {'lat': 43.2965}],
## 'text': 'Un tweet !',
## 'user_mentions': [{'id': 111, 'screen_name': 'nom_twittos1'},
## {'id': 112, 'screen_name': 'nom_twittos2'}]}
5.1.3.1 Importation depuis Internet
Encore une fois, il est possible d’importer des fichiers JSON depuis Internet :
import urllib
from urllib.request import urlopen
url = "http://egallic.fr/Enseignement/Python/fichiers_exemples/tweets.json"
with urllib.request.urlopen(url) as mon_fichier:
donnees = json.load(mon_fichier)
pprint(donnees)
## {'created_at': 'Wed Sep 26 07:38:05 +0000 2018',
## 'id': 11,
## 'loc': [{'long': 5.3698}, {'lat': 43.2965}],
## 'text': 'Un tweet !',
## 'user_mentions': [{'id': 111, 'screen_name': 'nom_twittos1'},
## {'id': 112, 'screen_name': 'nom_twittos2'}]}
5.1.4 Fichiers Excel
Les fichiers Excel (xls
ou xlsx
) sont aussi très largement répandus en économie. Le lecteur est prié de se référer à la Section 10.17.2 pour une méthode d’importation des données Excel avec la librairie pandas
.
5.2 Exporter des données
Il n’est pas rare de devoir exporter ses données, ne serait-ce que pour les partager. À nouveau, la fonction open()
est mise à contribution, en jouant avec la valeur du paramètre mode
(c.f. Tableau 5.1).
5.2.1 Fichiers textes
Admettons que nous ayons besoin d’exporter des lignes de texte dans un fichier. Avant de donner un exemple avec la fonction open()
, regardons deux fonctions importantes pour convertir les contenus de certains objets en texte.
La première, str()
, retourne une version en chaînes de caractères d’un objet. Nous l’avons déjà appliquée à des nombres que l’on désirait concaténer en Section 2.1.4.
x = ["pomme", 1, 3]
str(x)
Le résultat de cette instruction retourne la liste sous la forme d’une chaîne de caractères : "['pomme', 1, 3]"
.
La seconde fonction qu’il semble important d’aborder est repr()
. Cette fonction retourne une chaîne contenant une représentation imprimable à l’écran d’un objet. De plus, cette chaîne peut être lue par l’interprète.
y = "Fromage, tu veux du fromage ?\n"
repr(y)
Le résultat donne : "'Fromage, tu veux du fromage ?\\n'"
.
Admettons que nous souhaitons exporter deux lignes :
- la première, un texte qui indique un titre (“Caractéristiques de Kyrie Irving”) ;
- la seconde, un dictionnaire contenant des informations sur Kyrie Irving (c.f. ci-dessous).
Définissions ce dictionnaire :
z = { "nom": "Kyrie",
"prenom": "John",
"naissance": 1992,
"equipes": ["Cleveland", "Boston"]}
Une des syntaxes pour exporter les données au format txt
est :
# Ouverture en mode lecture (par défaut)
chemin = "chemin/vers/fichier.txt"
with open(chemin, "w") as mon_fichier:
fonction_pour_exporter()
On créé une variable indiquant le chemin vers le fichier. On ouvre ensuite le fichier en mode écriture en précisant le paramètre mode = "w"
. Puis, il reste à écrire nos lignes dans le fichier.
chemin = "./fichiers_exemples/Irving.txt"
with open(chemin, mode = "w") as mon_fichier:
mon_fichier.write("Caractéristiques de Kyrie Irving\n")
mon_fichier.writelines(repr(z))
Si le fichier est déjà existant, en ayant utilisé mode="w"
, l’ancien fichier sera écrasé par le nouveau. Si on souhaite ajouter des lignes au fichier existant, on utilisera mode="a"
par exemple :
with open(chemin, mode = "a") as mon_fichier:
mon_fichier.writelines("\nUne autre ligne\n")
Si on souhaite être prévenu si le fichier est déjà existant, et faire échouer l’écriture si tel est le cas, on peut utiliser mode="x"
:
with open(chemin, mode = "x") as mon_fichier:
mon_fichier.writelines("Une nouvelle ligne qui ne sera pas ajoutée\n")
## FileExistsError: [Errno 17] File exists: './fichiers_exemples/Irving.txt'
##
## Detailed traceback:
## File "<string>", line 1, in <module>
5.2.2 Fichiers CSV
En tant qu’économiste, il est plus fréquent d’avoir à exporter les données au format CSV plutôt que texte, du fait de la structure en rectangle des données que l’on manipule. Comme pour l’importation de CSV (c.f. Section 5.1.2), on utilise le module csv
. Pour écrire dans le fichier, on utilise la méthode writer()
. Les paramètres de formatage de cette fonction sont les mêmes que ceux de la fonction reader()
(c.f. Tableau 5.2).
Exemple de création d’un fichier CSV :
import csv
chemin = "./fichiers_exemples/fichier_export.csv"
with open(chemin, mode='w') as mon_fichier:
mon_fichier_ecrire = csv.writer(mon_fichier, delimiter=',',
quotechar='"',
quoting=csv.QUOTE_MINIMAL)
mon_fichier_ecrire.writerow(['Pays', 'Année', 'Trimestre', 'TC_PIB'])
mon_fichier_ecrire.writerow(['France', '2017', 'Q4', 0.7])
mon_fichier_ecrire.writerow(['France', '2018', 'Q1', 0.2])
Bien évidemment, la plupart du temps, nous n’écrivons pas à la main chaque entrée. Nous exportons les données contenues dans une structure. La Section 10.17.2 donne des exemples de ce type d’export, lorsque les données sont contenues dans des tableaux à deux dimension créés avec la librairie pandas
.
5.2.3 Fichier JSON
Il peut être nécessaire de sauvegarder des données structurées au format JSON, par exemple lorsqu’on a fait appel à une API (e.g., l’API de Twitter) qui retourne des objets au format JSON.
Pour ce faire, nous allons utiliser la librairire json
, et sa méthode dump()
. Cette méthode permet de sérialiser un objet (par exemple une liste, comme ce que l’on obtient avec l’API Twitter interrogée avec la libraririe twitter-python
) en JSON.
import json
x = [1, "pomme", ["pépins", "rouge"]]
y = { "nom": "Kyrie",
"prenom": "John",
"naissance": 1992,
"equipes": ["Cleveland", "Boston"]}
x_json = json.dumps(x)
y_json = json.dumps(y)
print("x_json: ", x_json)
## x_json: [1, "pomme", ["p\u00e9pins", "rouge"]]
print("y_json: ", y_json)
## y_json: {"nom": "Kyrie", "prenom": "John", "naissance": 1992, "equipes": ["Cleveland", "Boston"]}
Comme on peut le constater, on rencontre quelques petite problèmes d’affichage des caractères accentués. On peut préciser, à l’aide du paramètre ensure_ascii
évalué à False
que l’on ne désire pas s’assurer que les caractères non-ascii soient échappés par des séquences de type \uXXXX
.
x_json = json.dumps(x, ensure_ascii=False)
y_json = json.dumps(y, ensure_ascii=False)
print("x_json: ", x_json)
## x_json: [1, "pomme", ["pépins", "rouge"]]
print("y_json: ", y_json)
## y_json: {"nom": "Kyrie", "prenom": "John", "naissance": 1992, "equipes": ["Cleveland", "Boston"]}
chemin = "./fichiers_exemples/export_json.json"
with open(chemin, 'w') as f:
json.dump(json.dumps(x, ensure_ascii=False), f)
f.write('\n')
json.dump(json.dumps(y, ensure_ascii=False), f)
Si on souhaite réimporter dans Python le contenu du fichier export_json.json
:
chemin = "./fichiers_exemples/export_json.json"
with open(chemin, "r") as f:
data = []
for line in f:
data.append(json.loads(line, encoding="utf-8"))
print(data)
## ['[1, "pomme", ["pépins", "rouge"]]', '{"nom": "Kyrie", "prenom": "John", "naissance": 1992, "equipes": ["Cleveland", "Boston"]}']
5.2.4 Exercice
- Créer une liste nommée
a
contenant des informations sur le taux de chômage en France au deuxième trimestre 2018. Cette liste doit contenir trois éléments :- l’année ;
- le trimestre ;
- la valeur du taux de chômage (\(9.1\%\)).
- Exporter au format CSV le contenu de la liste
a
, en le faisant précéder d’une ligne précisant les noms des champs. Utiliser le point virgule comme séparateur de champs. - Importer le fichier créé dans la question précédente dans Python.