Fusionner des tables☘
Les exercices de cette page sont plus complexes: ils font appel à tout ce qui a été vu auparavant pour exploiter des données venant de plusieurs tables de données.
Ce type de fusion doit être maîtrisé.
Note
Ce type de travail sera prolongé en terminale avec l'étude du langage SQL.
Des clients et leurs commandes☘
On dispose d'un fichier client.csv
Contenu de client.csv
id_client | nom | prénom |
---|---|---|
1 | Bagou | Albert |
2 | Charabia | Barnabé |
3 | Blabla | Casimir |
4 | Paulitik | Zoé |
5 | Escro | Virgil |
6 | Manteux | Rémi |
et d'un fichier commande.csv.
Contenu de commande.csv
Le champ id_client fait référence au champ de même nom du fichier client.
Par exemple, la commande ayant l'id_commande égal à 1 a été faite par la personne id_client = 2, c'est à dire par Charabia Barnabé.
id_commande | id_client | descriptif |
---|---|---|
1 | 2 | bouilloire |
2 | 3 | Livre Apprende Python |
3 | 2 | Livre Apprendre HTML |
4 | 4 | livre Apprendre CSS |
5 | 6 | couverture |
6 | 4 | VTT |
7 | 4 | smartphone |
8 | 1 | cahiers |
9 | 2 | Livre Le réseau internet |
10 | 3 | Livre Les systèmes d’exploitation |
11 | 1 | livre Algorithmique |
Fusion☘
On aimerait les fusionner. Plus précisément, on vous demande de construire une liste de dictionnaires dans laquelle chaque dictionnaire se présente ainsi:
{'id_client': ..., 'nom': ..., 'prénom': ..., 'id_commande': ..., 'descriptif': ...}.
Bien sûr dans cette ligne, la commande doit avoir été faite par le client, ce qui signifie que l'identifiant client de la commande est bien l'identifiant du client correspondant aux nom et prénom obtenus.
Un client qui n'a pas fait de commande n'apparaîtra pas dans cette liste.
Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Tri de la fusion☘
Ordonnez la liste obtenue après fusion suivant l'ordre croissant des noms des clients et pour un même client suivant l'ordre croissant des id_commande.
Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Stokage du résultat dans un fichier☘
Avec la liste obtenue par fusion, vous créerez un fichier csv, en utilisant DictWriter. Il vous faudra commencer par lire la documentation associée.
Code pour créer le fichier avec dictionnaires
Une fonction pour créer un fichier csv à partir d'une liste de dictionnaires (présentant les mêmes champs).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
|
Des enseignants et leurs cours☘
On utilise dans cet exercice la table personnes.csv et la table cours.csv
la table personnes
id_personne | nom | prenom | anneeNaissance |
---|---|---|---|
1 | Labrosse | Adam | 2000 |
2 | Gemlamorte | Adèle | 1985 |
3 | Auboisdormant | Abel | 2001 |
4 | Etpan | Ahmed | 1975 |
5 | Térieur | Alain | 1999 |
6 | Térieur | Alex | 1976 |
7 | Proviste | Alain | 2000 |
8 | Verse | Alain | 1970 |
9 | Ception | Alex | 2001 |
10 | Ainé | Ali | 1975 |
11 | Gator | Ali | 2001 |
12 | Bistraux | Alonzo | 2001 |
13 | Patamob | Alphonse | 1970 |
14 | Ficulté | Andy | 1980 |
15 | Rectdustade | Andy | 2000 |
16 | Verserre | Annie | 2001 |
17 | Boréal | Aurore | 1985 |
18 | Nor | Paul | 1985 |
19 | Dejeu | Bernadette | 2001 |
20 | Dajeun | Bruno | 1984 |
21 | Hiple | Candice | 2000 |
la table cours
La colonne id_enseignant fait référence à la colonne id_personne de la table personnes.
Ainsi on sait, par exemple, que le cours sur la théorie des graphes est assuré par Adèle Gemlamorte.
id_cours | id_enseignant | intitule |
---|---|---|
1 | 2 | théorie des graphes |
2 | 4 | programmation objet |
3 | 6 | programmation fonctionnelle |
4 | 8 | théorie des automates |
5 | 10 | base de données relationnelle |
6 | 13 | réseaux |
7 | 14 | langage python |
8 | 17 | html et css |
9 | 18 | javascript |
10 | 20 | java |
11 | 2 | algorithmique |
12 | 4 | tests logiciels |
13 | 6 | intelligence artificielle |
14 | 8 | UML |
15 | 10 | XML |
16 | 13 | scheme |
17 | 14 | merise |
18 | 14 | webgl |
19 | Unix |
Vous devez créer une liste de dictionnaires. Les clefs de chaque dictionnaire seront 'id_personne', 'nom', 'prenom', 'id_cours', 'intitule'. Cette liste met donc en face de chaque personne les cours qu'elle assure.
Chaque personne devra apparaître dans la liste même si elle n'assure pas de cours ('id_cours' et 'intitule' seront dans ce cas associées à ''
).
Une personne assurant plusieurs cours apparaît sur autant de lignes...
Un cours qui n'est assuré par personne devra aussi apparaître (avec ''
pour valeur associée aux clefs identifiant l'enseignant).
La liste devra être triée suivant le nom des personnes (ordre croissant). Et pour une même personne, les lignes seront triées suivant le nom des cours (ordre croissant).
La liste créée sera envoyée dans un fichier csv.
Solution
import csv
def de_csv_vers_dico(fichier):
"""
fichier -- nom d'un fichier csv (sans l'extension)
renvoie la liste de dictionnaires associée au fichier.
"""
with open(fichier + '.csv', newline='') as fichiercsv:
lecture = csv.DictReader(fichiercsv, delimiter=',')
return [ligne for ligne in lecture]
def de_dico_vers_csv(liste, nomFichier):
"""
liste -- liste de dictionnaires
nomFichier -- nom du fichier créé (sans extension)
crée le fichier csv contenant les contenus des dictionnaires
"""
with open(nomFichier + '.csv', 'w', newline='') as fichiercsv:
entete = [clef for clef in liste[0].keys()]
ecriture = csv.DictWriter(fichiercsv, fieldnames=entete)
ecriture.writeheader()
for ligne in liste:
ecriture.writerow(ligne)
personnes = de_csv_vers_dico('personnes')
cours = de_csv_vers_dico('cours')
# premier parcours, on associe enseignant et cours
liste = []
for discipline in cours:
for personne in personnes:
if discipline['id_enseignant'] == personne['id_personne']:
dico = {'id_personne': personne['id_personne'],
'nom': personne['nom'],
'prenom': personne['prenom'],
'id_cours': discipline['id_cours'],
'intitule': discipline['intitule']
}
liste.append(dico)
# seconde boucle, on ajoute les personnes ne donnant pas de cours
for personne in personnes:
present = False
for dico in liste:
if personne['id_personne'] == dico['id_personne']:
present = True
if not present:
liste.append({'id_personne': personne['id_personne'],
'nom': personne['nom'],
'prenom': personne['prenom'],
'id_cours': '',
'intitule': ''}
)
# troisième boucle, on ajoute les cours n'ayant pas d'enseignant
for crs in cours:
present = False
for dico in liste:
if crs['id_cours'] == dico['id_cours']:
present = True
if not present:
liste.append({'id_personne': '',
'nom': '',
'prenom': '',
'id_cours': crs['id_cours'],
'intitule': crs['intitule']}
)
# on trie:
liste.sort(key= lambda x:x['intitule'])
liste.sort(key= lambda x:x['nom'])
de_dico_vers_csv(liste, 'enseignements')
Remarque sur le tri
L'ordre des lettres est l'ordre ASCII, les majuscules sont situées avant les minuscules, ce qui explique que par exemple pour Ali Ainé, le cours XML soit placé avant le cours 'base de données relationnelle'.
Pour règler ce problème, il suffit de trier suivant les chaînes préalablement toutes passées en minuscule, ce qui se fait facilement avec la méthode lower en remplaçant les deux lignes de tris par:
liste.sort(key= lambda x:x['intitule'].lower())
liste.sort(key= lambda x:x['nom'].lower())
Des acteurs et leurs rôles☘
On utilise ici trois tables:
la table personna
id_personne | nom | prenom |
---|---|---|
1 | Brasseur | Claude |
2 | Boon | Dany |
3 | Goldblum | Jeff |
4 | Reno | Jean |
5 | Balasko | Josiane |
6 | Olivares | Gerardo |
7 | Emmerich | Roland |
8 | Kidmann | Nicole |
9 | Kubrick | Stanley |
10 | Cruise | Tom |
11 | McQuarrie | Christopher |
12 | Spielberg | Steven |
13 | Ford | Harrison |
14 | Abrams | JJ |
15 | Merad | Kad |
16 | Rich | Claude |
17 | Tavernier | Bertrand |
18 | Robert | Yves |
19 | Berri | Claude |
20 | Aghion | Gabriel |
21 | Darmon | Gérard |
22 | Laroque | Michèle |
la table joue
id_acteur fait référence à l'id_personne de la table personna. id_film fait référence à l'id_film de la table film.
Ainsi, on sait que Nicole Kidmann (id_personne = 8) joue le rôle d'Alice (id_role = 1) dans "Eyes Wide Shut" (id_film = 1).
id_role | id_acteur | id_film | role |
---|---|---|---|
1 | 8 | 1 | Alice |
2 | 10 | 1 | Bill |
3 | 10 | 2 | Ethan Hunt |
4 | 10 | 3 | John Anderton |
5 | 13 | 6 | Indiana Jones |
6 | 13 | 7 | Han Solo |
7 | 2 | 8 | Antoine Bailleul |
8 | 15 | 8 | Philippe Abrams |
9 | 16 | 9 | Duc Clovis de Crassac |
10 | 1 | 10 | Daniel |
11 | 2 | 11 | Seb |
12 | 21 | 11 | Loïc |
13 | 22 | 11 | Marie Hagutte |
la table film
id_realisateur fait référence à id_personne de la table personna.
id_film | id_realisateur | titre | genre | annee |
---|---|---|---|---|
1 | 9 | Eyes Wide Shut | drame | 1999 |
2 | 11 | Mission impossible 5 | action | 2015 |
3 | 12 | Minority Report | SF | 2002 |
4 | 12 | Les dents de la mer | épouvante | 1975 |
5 | 12 | E.T. l'extraterrestre | SF | 1982 |
6 | 12 | Les aventuriers de l'Arche perdue | aventure | 1981 |
7 | 14 | Star Wars - Le Réveil de la Force | SF | 2015 |
8 | 2 | Bienvenue chez les Ch'tis | comédie | 2008 |
9 | 17 | La fille de D'Artagnan | cape et épée | 1994 |
10 | 18 | Un éléphant, ça trompe énormément | comédie | 1976 |
11 | 20 | Pédale dure | comédie | 2004 |
Créer une liste de dictionnaires présentant: nom et prénom de l'acteur, film dans lequel il joue, date du film, rôle dans le film, réalisateur du film.
La liste sera triée en ordre croissant des noms des acteurs et pour un même acteur en ordre décroissant des titres de film.
Vous créerez enfin un fichier csv contenant le résultat.
Solution
import csv
def de_csv_vers_dico(fichier):
"""
fichier -- nom d'un fichier csv (sans l'extension)
renvoie la liste de dictionnaires associée au fichier.
"""
with open(fichier + '.csv', newline='') as fichiercsv:
lecture = csv.DictReader(fichiercsv, delimiter=',')
return [ligne for ligne in lecture]
def de_dico_vers_csv(liste, nomFichier):
"""
liste -- liste de dictionnaires
nomFichier -- nom du fichier créé (sans extension)
crée le fichier csv contenant les contenus des dictionnaires
"""
with open(nomFichier + '.csv', 'w', newline='') as fichiercsv:
entete = [clef for clef in liste[0].keys()]
ecriture = csv.DictWriter(fichiercsv, fieldnames=entete)
ecriture.writeheader()
for ligne in liste:
ecriture.writerow(ligne)
personnes = de_csv_vers_dico('personna')
jeux = de_csv_vers_dico('joue')
films = de_csv_vers_dico('film')
liste = []
for acteur in personnes:
for joue in jeux:
if joue['id_acteur'] == acteur['id_personne']:
for film in films:
if joue['id_film'] == film['id_film']:
dico = {'nom': acteur['nom'],
'prenom': acteur['prenom'],
'film': film['titre'],
'annee': film['annee'],
'rôle': joue['role']
}
for realisateur in personnes:
if film['id_realisateur'] == realisateur['id_personne']:
dico['réalisateur'] = realisateur['nom']+' '+realisateur['prenom']
liste.append(dico)
# on trie:
liste.sort(key= lambda x:x['film'].lower(), reverse= True)
liste.sort(key= lambda x:x['nom'].lower())
de_dico_vers_csv(liste, 'rolesActeurs')