Aller au contenu

✂ Fusionner des tables⚓︎

On considère dans ce sujet les trois fichiers csv décrits ci-dessous :

countries.csv contient des informations décrivant les pays :

  • CountryCode : le code du pays (texte, clé primaire)

  • Name : le nom du pays (texte)

  • Continent : le continent du pays (texte)

  • SurfaceArea : la surface du pays (nombre décimal)

  • Population : la population du pays (entier)

  • Capital : la capitale du pays (nombre entier correspondant à un ID dans le fichier cities.csv)

  • d'autres descripteurs qui ne nous intéressent pas ici...

languages.csv contient les informations sur les langues parlées dans chaque pays :

  • CountryCode : le code du pays (texte)

  • Language : la langue concernée par cette entrée (texte)

  • IsOfficial : cette langue est-elle officielle dans ce pays ? (texte, T pour True, F pour False)

  • Percentage : le pourcentage de locuteurs dans le pays (nombre décimal)

cities.csv contient des informations décrivant des villes :

  • ID : l'identifiant de la ville (entier)

  • Name : le nom de la ville (texte)

  • code : le code du pays dans lequel est situé la ville (texte)

  • District : la région d'appartenance de la ville (texte)

  • Population : la population de la ville (entier)

Import réalisés !

Dans toute la suite du TP, les listes pays, langues et villes contiennent les dictionnaires correspondant aux imports de ces différents fichiers.

Les données sont correctement typées (en particulier les valeurs isOfficial de la liste langues qui sont des booléens).

🐍 Script Python
pays = [
    {"CountryCode": "ABW", "Name": "Aruba", "Continent": "North America", ...},
    {"CountryCode": "AFG", "Name": "Afghanistan", "Continent": "Asia", ...},
    ...
]

langues = [
    {"CountryCode" : "ABW", "Language": "Dutch", "IsOfficial": True, "Percentage": 5.3},
    {"CountryCode" : "ABW", "Language": "English", "IsOfficial": False, "Percentage": 9.5},
    ...
]

villes = [
    {"ID": 1, "Name": "Kabul", "code": "AFG",, "District": "Kabol", "Population": 1780000},
    {"ID": 2, "Name": "Qandahar", "code": "AFG",, "District": "Qandahar", "Population": 237500},
    ...
]

Langues parlées dans chaque pays⚓︎

Quelles sont les langues parlées en Haïti ? Pour le savoir il faut :

  • parcourir la liste pays jusqu'à trouver le code de Haïti (orthographié Haiti dans la liste pays),

  • parcourir la liste langues et en extraire les valeurs correspondant à ce code.

Langues parlées en Haïti

Compléter le code ci-dessous permettant de déterminer les langues parlées en Haïti.

###
# Testbksl-nlassert code == "HTI", "Erreur de code"bksl-nlassert languespy-undhaiti == [bksl-nl {"CountryCode": "HTI", "Language": "French", "IsOfficial": True, "Percentage": 0.0},bksl-nl {"CountryCode": "HTI", "Language": "Haiti Creole", "IsOfficial": False, "Percentage": 100.0},bksl-nl], "Erreur dans la recherche"bksl-nlbksl-nl 5/5
#--- HDR ---#bksl-nlfrom js import fetchbksl-nlimport csvbksl-nlbksl-nl##########bksl-nl# Villes #bksl-nl##########bksl-nlbksl-nlurlpy-undfichier = "cities.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlvilles = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["ID"] = int(entree["ID"])bksl-nl entree["Population"] = int(entree["Population"])bksl-nl villes.append(entree)bksl-nlbksl-nl###########bksl-nl# Langues #bksl-nl###########bksl-nlbksl-nlurlpy-undfichier = "languages.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlbksl-nllangues = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["Percentage"] = float(entree["Percentage"])bksl-nl entree["IsOfficial"] = True if entree["IsOfficial"] == "T" else Falsebksl-nl langues.append(entree)bksl-nlbksl-nl########bksl-nl# Pays #bksl-nl########bksl-nlbksl-nlurlpy-undfichier = "countries.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlpays = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["SurfaceArea"] = float(entree["SurfaceArea"])bksl-nl entree["GNP"] = float(entree["GNP"])bksl-nl entree["Population"] = int(entree["Population"])bksl-nl entree["Capital"] = int(entree["Capital"]) if entree["Capital"] else -1bksl-nl pays.append(entree)bksl-nl#--- HDR ---#bksl-nlipy-undhaiti = 0bksl-nlwhile pays[ipy-undhaiti]["Name"] ... "Haiti":bksl-nl ipy-undhaiti = ...bksl-nlbksl-nlcode = pays[ipy-undhaiti][...]bksl-nlbksl-nlbksl-nllanguespy-undhaiti = []bksl-nlfor entree in langues:bksl-nl if entree[...] == code:bksl-nl languespy-undhaiti.append(entree)bksl-nlbksl-nlfor langue in languespy-undhaiti:bksl-nl print(langue)bksl-nl bksl-nlipy-undhaiti = 0bksl-nlwhile pays[ipy-undhaiti]["Name"] != "Haiti":bksl-nl ipy-undhaiti += 1bksl-nlbksl-nlcode = pays[ipy-undhaiti]["CountryCode"]bksl-nlbksl-nllanguespy-undhaiti = []bksl-nlfor entree in langues:bksl-nl if entree["CountryCode"] == code:bksl-nl languespy-undhaiti.append(entree)bksl-nlbksl-nl

A

La boucle while dans la recherche du code d'Haiti pourrait aussi être remplacée par un for accompagné de l'instruction break qui interrompt la boucle :

🐍 Script Python
for entree in pays:
    if entree["Name"] == "Haiti":
        code = entree["CountryCode"]
        break

Z

Le descripteur CountryCode permet donc de faire le lien entre les deux listes pays et langues.

Utilisons cette relation afin de déterminer les langues parlées dans un pays quelconque.

Langues parlées dans un pays

On demande d'écrire deux fonctions :

  • code_pays prend en argument la liste des pays ainsi que le nom d'un pays et renvoie son code ;

  • langues_parlees prend en argument les listes des données des pays et celle des langues (arguments pays et langues) ainsi que le nom d'un pays (nom) et renvoie la liste des noms des langues parlées dans ce pays.

Exemples

🐍 Console Python
>>> code_pays(pays, "Haiti")
"HTI"
>>> langues_parlees(pays, langues, "Haiti")
['French', 'Haiti Creole']

###
# Test publicbksl-nlassert sorted(languespy-undparlees(pays, langues, "Haiti")) == ['French', 'Haiti Creole']bksl-nlbksl-nl# Tests supplémentairesbksl-nldef codepy-undpayspy-undcorr(pays, nom):bksl-nl for entree in pays:bksl-nl if entree["Name"] == nom:bksl-nl return entree["CountryCode"]bksl-nlbksl-nl raise ValueError("Le nom n'apparaît pas dans la liste")bksl-nlbksl-nlbksl-nldef languespy-undcorr(pays, langues, nom):bksl-nl code = codepy-undpayspy-undcorr(pays, nom)bksl-nl bksl-nl resultat = []bksl-nl for entree in langues:bksl-nl if entree["CountryCode"] == code:bksl-nl resultat.append(entree["Language"])bksl-nl bksl-nl return resultatbksl-nlbksl-nlbksl-nlfrom random import randrangebksl-nlfor py-und in range(5):bksl-nl indice = randrange(0, len(pays))bksl-nl nom = pays[indice]["Name"]bksl-nl attendu = pays[indice]["CountryCode"]bksl-nl assert codepy-undpays(pays, nom) == attendu, f"Erreur en cherchant le code de {nom}"bksl-nl attendu = sorted(languespy-undcorr(pays, langues, nom))bksl-nl assert sorted(languespy-undparlees(pays, langues, nom)) == attendu, f"Erreur pour les langues de {nom}"bksl-nl 5/5
#--- HDR ---#bksl-nlfrom js import fetchbksl-nlimport csvbksl-nlbksl-nl##########bksl-nl# Villes #bksl-nl##########bksl-nlbksl-nlurlpy-undfichier = "cities.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlvilles = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["ID"] = int(entree["ID"])bksl-nl entree["Population"] = int(entree["Population"])bksl-nl villes.append(entree)bksl-nlbksl-nl###########bksl-nl# Langues #bksl-nl###########bksl-nlbksl-nlurlpy-undfichier = "languages.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlbksl-nllangues = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["Percentage"] = float(entree["Percentage"])bksl-nl entree["IsOfficial"] = True if entree["IsOfficial"] == "T" else Falsebksl-nl langues.append(entree)bksl-nlbksl-nl########bksl-nl# Pays #bksl-nl########bksl-nlbksl-nlurlpy-undfichier = "countries.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlpays = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["SurfaceArea"] = float(entree["SurfaceArea"])bksl-nl entree["GNP"] = float(entree["GNP"])bksl-nl entree["Population"] = int(entree["Population"])bksl-nl entree["Capital"] = int(entree["Capital"]) if entree["Capital"] else -1bksl-nl pays.append(entree)bksl-nl#--- HDR ---#bksl-nldef codepy-undpays(pays, nom):bksl-nl """Renvoie le code d'un pays"""bksl-nl ...bksl-nlbksl-nlbksl-nldef languespy-undparlees(pays, langues, nom):bksl-nl """Renvoie la liste des noms des langues parlées dans le pays indiqué par son nom"""bksl-nl ...bksl-nlbksl-nlassert sorted(languespy-undparlees(pays, langues, "Haiti")) == ['French', 'Haiti Creole']bksl-nldef codepy-undpays(pays, nom):bksl-nl """Renvoie le code d'un pays"""bksl-nl for entree in pays:bksl-nl if entree["Name"] == nom:bksl-nl return entree["CountryCode"]bksl-nlbksl-nl raise ValueError("Le nom n'apparaît pas dans la liste")bksl-nlbksl-nlbksl-nldef languespy-undparlees(pays, langues, nom):bksl-nl """Renvoie la liste des noms des langues parlées dans le pays indiqué par son nom"""bksl-nl code = codepy-undpays(pays, nom)bksl-nl bksl-nl resultat = []bksl-nl for entree in langues:bksl-nl if entree["CountryCode"] == code:bksl-nl resultat.append(entree["Language"])bksl-nl bksl-nl return resultatbksl-nl

A

Contrairement à l'exemple de Haïti précédent, on peut ici utiliser une boucle for sans avoir recours à l'instruction break. En effet, le return joue ce rôle.

On a de plus ajouté la ligne raise ValueError("Le nom n'apparaît pas dans la liste") afin de gérer les cas où le nom passé en argument ne correspond à aucun pays. On est dans ce cas de figure si l'on a effectué la totalité du parcours (de la boucle for) sans avoir renvoyé de résultat.

Z

Capitales⚓︎

Quelle est la capitale d'Haïti ? Là encore, il faut :

  • parcourir la liste des pays jusqu'à trouver l'entrée correspondant à Haïti,

  • repérer le code de la capitale correspondante,

  • parcourir la liste des villes jusqu'à trouver le code cherché.

Nous allons effectuer ces actions pour chacun des pays présents dans la liste. La capitale étant trouvée, nous ajouterons une nouvelle clé CapitalName au dictionnaire du pays. La valeur associée sera le nom de la capitale obtenu.

Pas de capitale ?

Certains des « pays » listés n'en sont pas vraiment et n'ont donc pas de capitale. C'est par exemple le cas de l'Antarctique.

Lors de l'import des données, on leur a associé la valeur -1 à la clé Capital.

Liens

Quels sont les descripteurs permettant de faire le lien entre les listes pays et villes ?

  • Le descripteur "Capital" de pays et "Name" de villes
  • Le descripteur "Name" de pays et "Name" de villes
  • Le descripteur "Capital" de pays et "ID" de villes
  • Le descripteur "ID" de pays et "Capital" de villes
  • ❌ Le descripteur "Capital" de pays et "Name" de villes
  • ❌ Le descripteur "Name" de pays et "Name" de villes
  • ✅ Le descripteur "Capital" de pays et "ID" de villes
  • ❌ Le descripteur "ID" de pays et "Capital" de villes
Associer les capitales aux pays

Compléter le code ci-dessous afin d'ajouter à chaque dictionnaire correspondant à un pays une nouvelle entrée CapitalName contenant le nom de sa capitale.

On utilisera la chaîne vide "" comme valeur pour les « pays » sans capitale.

Ainsi :

  • le dictionnaire correspondant à la France contiendra un nouveau couple "CapitalName": "Paris",

  • celui de l'Antarctique "CapitalName": "".

###
# Testbksl-nlfor entree in pays:bksl-nl capitale = entree["Capital"]bksl-nl if capitale == -1:bksl-nl assert entree["CapitalName"] == "", f"Erreur pour {entree['Name']}"bksl-nl else:bksl-nl for ville in villes:bksl-nl if ville["ID"] == capitale: bksl-nl assert entree["CapitalName"] == ville["Name"], f"Erreur pour {entree['Name']}"bksl-nl breakbksl-nl 5/5
#--- HDR ---#bksl-nlfrom js import fetchbksl-nlimport csvbksl-nlbksl-nl##########bksl-nl# Villes #bksl-nl##########bksl-nlbksl-nlurlpy-undfichier = "cities.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlvilles = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["ID"] = int(entree["ID"])bksl-nl entree["Population"] = int(entree["Population"])bksl-nl villes.append(entree)bksl-nlbksl-nl###########bksl-nl# Langues #bksl-nl###########bksl-nlbksl-nlurlpy-undfichier = "languages.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlbksl-nllangues = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["Percentage"] = float(entree["Percentage"])bksl-nl entree["IsOfficial"] = True if entree["IsOfficial"] == "T" else Falsebksl-nl langues.append(entree)bksl-nlbksl-nl########bksl-nl# Pays #bksl-nl########bksl-nlbksl-nlurlpy-undfichier = "countries.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlpays = []bksl-nlwith open(urlpy-undfichier, "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=",")bksl-nl for entree in lecteur:bksl-nl entree["SurfaceArea"] = float(entree["SurfaceArea"])bksl-nl entree["GNP"] = float(entree["GNP"])bksl-nl entree["Population"] = int(entree["Population"])bksl-nl entree["Capital"] = int(entree["Capital"]) if entree["Capital"] else -1bksl-nl pays.append(entree)bksl-nl#--- HDR ---#bksl-nl# Compléter icibksl-nlbksl-nlprint(f"La capitale de la {pays[72]['Name']} est {pays[72]['CapitalName']}.")bksl-nlbksl-nlfor entree in pays:bksl-nl capitale = entree["Capital"]bksl-nl if capitale == -1:bksl-nl entree["CapitalName"] = ""bksl-nl else:bksl-nl fait = Falsebksl-nl i = 0bksl-nl while not fait:bksl-nl ville = villes[i]bksl-nl if ville["ID"] == capitale:bksl-nl entree["CapitalName"] = ville["Name"]bksl-nl fait = Truebksl-nl else:bksl-nl i += 1bksl-nl bksl-nl

A

Z