Exercices¶
Cet exercice vient en deux versions, une de niveau basique et une de niveau intermédiaire.
La version basique est une application de la technique d’indexation que l’on a vue dans le complément “Gérer des enregistrements”. On peut très bien faire les deux versions dans l’ordre, une fois qu’on a fait la version basique on est en principe un peu plus avancé pour aborder la version intermédiaire.
Contexte¶
Nous allons commencer à utiliser des données un peu plus réalistes. Il s’agit de données obtenues auprès de MarineTraffic - et légèrement simplifiées pour les besoins de l’exercice. Ce site expose les coordonnées géographiques de bateaux observées en mer au travers d’un réseau de collecte de type crowdsourcing.
De manière à optimiser le volume de données à transférer, l’API de MarineTraffic offre deux modes pour obtenir les données :
mode étendu : chaque mesure (bateau x position x temps) est accompagnée de tous les détails du bateau (
id, nom, pays de rattachement, etc.) ;mode abrégé : chaque mesure est uniquement attachée à l’
iddu bateau.
En effet, chaque bateau possède un identifiant unique qui est un entier, que l’on note id.
Chargement des données¶
Commençons par charger les données de l’exercice :
from corrections.exo_marine_dict import extended, abbreviatedFormat des données¶
Le format de ces données est relativement simple, il s’agit dans les deux cas d’une liste d’entrées - une par bateau.
Chaque entrée à son tour est une liste qui contient :
mode étendu: [id, latitude, longitude, date_heure, nom_bateau, code_pays, ...]
mode abrégé: [id, latitude, longitude, date_heure]sachant que les entrées après le code pays dans le format étendu ne nous intéressent pas pour cet exercice.
# une entrée étendue est une liste qui ressemble à ceci
sample_extended_entry = extended[3]
print(sample_extended_entry)[255801560, 49.3815, -4.412167, '2013-10-08T21:51:00', 'AUTOPRIDE', 'PT', '', 'ZEEBRUGGE']
# une entrée abrégée ressemble à ceci
sample_abbreviated_entry = abbreviated[0]
print(sample_abbreviated_entry)[227254910, 49.91799, -5.315172, '2013-10-08T22:59:00']
On précise également que les deux listes extended et abbreviated :
possèdent exactement le même nombre d’entrées ;
et correspondent aux mêmes bateaux ;
mais naturellement à des moments différents ;
et pas forcément dans le même ordre.
Exercice - niveau basique¶
# chargement de l'exercice
from corrections.exo_marine_dict import exo_indexBut de l’exercice¶
On vous demande d’écrire une fonction index qui calcule, à partir de la liste des données étendues, un dictionnaire qui est :
indexé par l’
idde chaque bateau ;et qui a pour valeur la liste qui décrit le bateau correspondant.
De manière plus imagée, si :
extended = [ bateau1, bateau2, ... ]Et si :
bateau1 = [ id1, latitude, ... ]On doit obtenir comme résultat de index un dictionnaire :
{
id1 -> [ id_bateau1, latitude, ... ],
id2 ...
}Bref, on veut pouvoir retrouver les différents éléments de la liste extended par accès direct, en ne faisant qu’une seule recherche dans l’index.
# le résultat attendu
result_index = exo_index.resultat(extended)
# on en profite pour illustrer le module pprint
from pprint import pprint
# à quoi ressemble le résultat pour un bateau au hasard
for key, value in result_index.items():
print("==== clé")
pprint(key)
print("==== valeur")
pprint(value)
breakThe history saving thread hit an unexpected error (OperationalError('disk I/O error')).History will not be written to the database.==== clé
992271012
==== valeur
[992271012, 47.64744, -3.509282, '2013-10-08T21:50:00', 'PENMEN', 'FR', '', '']
Remarquez ci-dessus l’utilisation d’un utilitaire parfois pratique : le module pprint pour pretty-printer.
Votre code¶
def index(extended):
"<votre_code>"Validation¶
exo_index.correction(index, abbreviated)Vous remarquerez d’ailleurs que la seule chose que l’on utilise dans cet exercice, c’est que l’id des bateaux arrive en première position (dans la liste qui matérialise le bateau), aussi votre code doit marcher à l’identique avec les bateaux étendus :
exo_index.correction(index, extended)Exercice - niveau intermédiaire¶
# chargement de l'exercice
from corrections.exo_marine_dict import exo_mergeBut de l’exercice¶
On vous demande d’écrire une fonction merge qui fasse une consolidation des données, de façon à obtenir en sortie un dictionnaire :
id -> [nom_bateau, code_pays, position_etendu, position_abrege]dans lequel les deux objets position sont tous les deux des tuples de la forme :
(latitude, longitude, date_heure)Voici par exemple un couple clé-valeur dans le résultat attendu :
# le résultat attendu
result_merge = exo_merge.resultat(extended, abbreviated)
# à quoi ressemble le résultat pour un bateau au hasard
from pprint import pprint
for key_value in result_merge.items():
pprint(key_value)
break(992271012,
['PENMEN',
'FR',
(47.64744, -3.509282, '2013-10-08T21:50:00'),
(47.64748, -3.509307, '2013-10-08T22:56:00')])
Votre code¶
def merge(extended, abbreviated):
"votre code"Validation¶
exo_merge.correction(merge, extended, abbreviated)Les fichiers de données complets¶
Signalons enfin pour ceux qui sont intéressés que les données chargées dans cet exercice sont disponibles au format JSON - qui est précisément celui exposé par marinetraffic.
Nous avons beaucoup simplifié les données d’entrée pour vous permettre une mise au point plus facile. Si vous voulez vous amuser à charger des données un peu plus significatives, sachez que :
vous avez accès aux fichiers de données plus complets :
pour charger ces fichiers, qui sont donc au format JSON, la connaissance intime de ce format n’est pas nécessaire, on peut tout simplement utiliser le module
json. Voici le code utilisé dans l’exercice pour charger ces JSON en mémoire ; il utilise des notions que nous verrons dans les semaines à venir :
# load data from files
import json
with open("data/marine-e1-ext.json", encoding="utf-8") as feed:
extended_full = json.load(feed)
with open("data/marine-e1-abb.json", encoding="utf-8") as feed:
abbreviated_full = json.load(feed)Une fois que vous avez un code qui fonctionne vous pouvez le lancer sur ces données plus copieuses en faisant :
exo_merge.correction(merge, extended_full, abbreviated_full)