2.3.2. File I/O Bonus#
Nous avons déjà abordé un grand nombre de sujets en une journée, mais votre professeur a également rédigé des instructions sur la lecture et l’écriture de données dans d’autres formats ! Le tutoriel suivant sera donc laissé à votre disposition pour que vous puissiez l’expérimenter chez vous.
2.3.2.1. Données structurées avec JSON#
JSON est un format populaire pour les données structurées qui peut être utilisé dans Python et Perl, entre autres langages. Le format JSON est construit sur une collection de paires nom/valeur. Les informations sur le nom peuvent être un objet, un enregistrement, un dictionnaire, une table de hachage, une liste à clés ou un tableau associatif. La valeur associée au nom peut être un tableau, un vecteur, une liste ou une séquence.
Nous pouvons utiliser le paquetage json
pour les entrées-sorties. La syntaxe du paquet est très similaire à celle de pickle
:
dump()
: écriture d’une chaîne encodée dans un fichier.load()
: Décodage lors de la lecture d’un fichier JSON.dumps()
: encodage en objets JSONloads()
: Décode la chaîne JSON.
Exemple de données JSON
{
"stations" : [
{
"acronyme" : "BLD",
"nom" : "Boulder Colorado",
"latitude" : 40.00,
"longitude" : -105.25
},
{
"acronyme" : "BHD",
"name" : "Baring Head Wellington New Zealand",
"latitude" : -41.28,
"longitude" : 174.87
}
]
}
Essayons de lire ce cadre de données JSON avec json
!
import json
json_data = '{"stations": [{"acronym": "BLD", \
"nom": "Boulder Colorado", \
"latitude": 40.00, \
"longitude": -105.25}, \
{"acronym": "BHD", \
"nom": "Baring Head Wellington New Zealand",\
"latitude": -41.28, \
"longitude": 174.87}]}'
python_obj = json.loads(json_data)
for x in python_obj['stations']:
print(x["nom"])
Boulder Colorado
Baring Head Wellington New Zealand
### Convertir python_obj en JSON
print(json.dumps(python_obj, sort_keys=True, indent=4))
{
"stations": [
{
"acronym": "BLD",
"latitude": 40.0,
"longitude": -105.25,
"nom": "Boulder Colorado"
},
{
"acronym": "BHD",
"latitude": -41.28,
"longitude": 174.87,
"nom": "Baring Head Wellington New Zealand"
}
]
}
Nous allons maintenant essayer de convertir un objet python en JSON et de l’écrire dans un fichier.
La syntaxe pour la sérialisation et la désérialisation dans le paquet json
est presque la même que celle de pickle
# Convertir les objets python en JSON
x = {
"prénom" : "John",
"âge" : 30,
"marié" : True,
"divorcé" : False,
"enfants" : ("Ann", "Billy"),
"animaux" : None,
"voitures" : [
{"modèle" : "BMW 230", "mpg" : 27.5},
{"Modèle" : "Ford Edge", "mpg" : 24.1}
]
}
# Sérialisation
with open('./pythonobj.json','w') as sid :
json.dump(x,sid)
# Désérialisation
with open('./pythonobj.json', 'r') as sid :
z = json.load(sid)
print(z)
{'prénom': 'John', 'âge': 30, 'marié': True, 'divorcé': False, 'enfants': ['Ann', 'Billy'], 'animaux': None, 'voitures': [{'modèle': 'BMW 230', 'mpg': 27.5}, {'Modèle': 'Ford Edge', 'mpg': 24.1}]}
2.3.2.2. Données quadrillées à N dimensions avec NetCDF4#
Les jeux de données géoscientifiques contiennent souvent plusieurs dimensions. Par exemple, les résultats des modèles climatiques contiennent généralement 4 dimensions : le temps (t), le niveau vertical (z), la longitude (lon) et la latitude (lat). Ces données sont trop complexes pour être stockées dans des tableaux.
Développé par Unidata (une filiale de UCAR), le format NetCDF contient une structure hiérarchique qui permet une meilleure organisation et un meilleur stockage de grands ensembles de données multidimensionnelles, d’informations sur les axes et d’autres métadonnées. Il est bien adapté à la gestion de grands ensembles de données numériques, car il permet aux utilisateurs d’accéder à des parties d’un ensemble de données sans avoir à le charger entièrement en mémoire.
Nous pouvons utiliser le paquetage netCDF4
pour créer, lire et stocker des données dans NetCDF4. Un autre paquetage, xarray
, est également disponible pour ce format de données.
2.3.2.2.1. Voici comment vous créez et stockez normalement des données dans un fichier netCDF:#
Ouvrez/créez un jeu de données netCDF.
Définissez les dimensions des données.
Construire des variables netCDF en utilisant les dimensions définies.
Transférer les données dans les variables netCDF.
Ajouter des attributs aux variables et à l’ensemble de données (facultatif mais recommandé).
Fermez le jeu de données netCDF.
2.3.2.2.1.1. Ouvrir un jeu de données netCDF4#
ncfid = netCDF4.Dataset('sample_netcdf.nc', mode='w', format='NETCDF4')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[6], line 1
----> 1 ncfid = netCDF4.Dataset('sample_netcdf.nc', mode='w', format='NETCDF4')
NameError: name 'netCDF4' is not defined
modeType
a les options suivantes :
‘w’ : pour créer un nouveau fichier
‘r+’ : pour lire et écrire dans un fichier existant
‘r’ : pour lire (uniquement) un fichier existant
‘a’ : pour ajouter un fichier à un fichier existant
fileFormat
a les options suivantes :
‘NETCDF3_CLASSIC’ : Format netCDF original
‘NETCDF3_64BIT_OFFSET’ : Utilisé pour alléger les restrictions de taille des fichiers netCDF classiques.
‘NETCDF4_CLASSIC’
‘NETCDF4’ : Offre de nouvelles fonctionnalités telles que les groupes, les types composés, les tableaux de longueur variable, les nouveaux types d’entiers non signés, l’accès parallèle aux E/S, etc.
‘NETCDF3_64BIT_DATA’
2.3.2.2.1.2. Création de dimensions dans un fichier netCDF#
Déclarez les dimensions avec
.createDimension(size)
Pour des dimensions illimitées, utilisez
None
ou0
comme taille.Les dimensions de taille illimitée doivent être déclarées avant (“à gauche de”) les autres dimensions.
# Définir les dimensions des données
time = ncfid.createDimension('time', None)
lev = ncfid.createDimension('lev', 72)
lat = ncfid.createDimension('lat', 91)
lon = ncfid.createDimension('lon', 144)
##########################################################################################
# Créer des variables de dimension et des variables de données pré-remplies avec fill_value
##########################################################################################
# Variables de dimension
times = ncfid.createVariable('time','f8',('time',))
levels = ncfid.createVariable('lev','i4',('lev',))
latitudes = ncfid.createVariable('lat','f4',('lat',))
longitudes = ncfid.createVariable('lon','f4',('lon',))
# Variable de données pré-remplie
temp = ncfid.createVariable('temp','f4',
('time', 'lev', 'lat', 'lon',),
fill_value=1.0e15)
2.3.2.2.1.3. Ajouter des attributs variables#
import datetime
latitudes.long_name = 'latitude'
latitudes.units = 'degrés nord'
longitudes.nom_long = 'longitude'
longitudes.units = 'degrés est'
levels.long_name = 'niveaux verticaux'
levels.units = 'hPa'
levels.positive = 'down'
beg_date = datetime.datetime(year=2019, month=1, day=1)
times.long_name = 'temps'
times.units = beg_date.strftime('heures depuis %Y-%m-%d %H:%M:%S')
times.calendar = 'gregorian'
temp.long_name = 'température'
temp.units = 'K'
temp.nom_standard = 'température_atmosphérique'
2.3.2.2.1.4. Écrire des données dans un fichier#
latitudes[ :] = np.arange(-90,91,2.0)
longitudes[ :] = np.arange(-180,180,2.5)
levels[ :] = np.arange(0,72,1)
out_frequency = 3 # fréquence de sortie en heures
num_records = 5
dates = [beg_date + n*datetime.timedelta(hours=out_frequency) for n in range(num_records)]
times[ :] = netCDF4.date2num(dates, units=times.units, calendar=times.calendar)
for i in range(num_records) :
temp[i, :,:, :] = np.random.uniform(size=(levels.size,
latitudes.size,
longitudes.size))
ncfid.close()
2.3.2.2.2. Nous allons maintenant lire le fichier netCDF4 stocké pour voir ce que nous venons de faire.#
databank = netCDF4.Dataset('./sample_netcdf.nc', mode='r')
# Nous imprimons les noms des variables dans le fichier `sample_netcdf.nc`.
print(databank.variables.keys())
# Nous pouvons lire les données comme suit
time = ncfid.variables['time'][:]
lev = ncfid.variables['lev'][:]
lat = ncfid.variables['lat'][:]
lon = ncfid.variables['lon'][:]
temp = ncfid.variables['temp'][:]
Important
Lors de la lecture de données à partir d’un fichier :
Si vous n’incluez pas
[ :]
à la fin devariables[var_name]
, vous obtenez un objet variable.Si vous incluez
[ :]
(ou[ :,:]
,[0, i:j, :]
, etc.) à la fin devariables[var_name]
, vous obtenez le tableau Numpy contenant les données.
print(lat)