T3.2 Opérations sur les tables⚓︎
L'objectif maintenant est d'exploiter les données représentées sous forme d'une table. Puisque celle-ci est une liste de dictionnaires, on va utiliser les techniques de manipulation des listes et dictionnaires déjà rencontrées.
Pour illustrer ces différentes techniques dans les exemples et exercices suivants, on utilisera cette table.
3.2.1 Recherche et agrégation⚓︎
Recherche
On souhaite d'abord vérifier qu'une valeur appartient à une table ou non. Pour cela il suffit de parcourir les enregistrements de la table et vérifier que la valeur recherchée est une valeur de l'enregistrement.
Recherche d'une valeur dans une table (à compléter) | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Correction
Exercice 1
Dans la pratique, la fonction précédente n'a que peu d'intérêt. On va plutôt rechercher si une valeur est présente dans un champ donné. Ainsi on n'a pas besoin de parcourir toutes les valeurs d'un enregistrement.
Modifier alors la fonction précédente pour qu'elle prenne en paramètre un champ et qu'elle recherche si la valeur est présente pour le champ précisé.
Exercice 2
On souhaite désormais récupérer certaines données si la valeur recherchée est trouvée.
Modifier la fonction précédente (ou en créer une nouvelle) pour qu'elle renvoie la liste des valeurs correspondant à un champ 2 (de retour) lorsque la valeur cherchée est trouvée (dans un champ 1 de recherche).
Par exemple, si table_sw
est la table contenant les données du fichier 'sw.csv':
>>> recherche('Jedi', 'Statut', 'Nom', table_sw)
['Obi-Wan Kenobi', 'Yoda', 'Luke Skywalker', 'Rey']
Agrégation
Il s'agit de récupérer une donnée statistique sur les données contenues dans une table, par exemple pour compter le nombre d'enregistrements qui satisfont à une certaine condition.
Exercice 3
Écrire une fonction compte
qui prend en paramètre une valeur, un champ et une table et renvoie le nombre d'occurences de la valeur dans le champ de la table.
Par exemple:
>>> compte('Droïde', 'Espèce', table_sw)
3
3.2.2 Sélection⚓︎
Sélection d'une ligne vérifiant un critère
On cherche ici à créer une nouvelle table en extrayant les enregistrements d'une table existante vérifiant un certain critère. Par exemple si on veut tous les enregistrements dont le statut est Jedi
, on veut extraire la table:
Nom | Espèce | Force | Statut |
---|---|---|---|
Obi-Wan Kenobi | Humain | oui | Jedi |
Rey | Humain | oui | Jedi |
Yoda | Yoda | oui | Jedi |
Luke Skywalker | Humain | oui | Jedi |
Cela consiste donc à créer une liste en parcourant la table existante et en sélectionnant les enregistrements selon un critère: c'est exactement ainsi qu'on crée une liste en compréhension avec filtre .
Par exemple, on peut créer la table précédente en sélectionnant les enregistrements dont la valeur du champ 'Statut'
est 'Jedi'
avec :
table_jedi = [enregistrement for enregistrement in table_sw if enregistrement['Statut'] == 'Jedi']
Exercice 4
- Créer la table des personnages d'espèce humaine.
- Créer la table des personnages d'espèce humaine qui maîtrisent la force.
Sélection de colonnes
On peut également avoir à extraire d'une table certaines colonnes, c'est-à-dire seulement des données d'un ou plusieurs champs. On appelle également cette opération projection1.
Par exemple, on veut créer la table suivante:
Nom | Espèce |
---|---|
Dark Vador | Humain |
Obi-Wan Kenobi | Humain |
R2-D2 | Droïde |
... | ... |
Jango Fett | Humain |
Il s'agit donc de créer une nouvelle table (liste) dont les enregistrements sont des dictionnaires qui ne contiennent que les couples champ: valeur
des enregistrements de la table initiale pour les champs précisés (sous forme d'une liste par exemple).
Exercice 5
-
Compléter la fonction de projection:
Fonction de projection (à compléter) 1 2 3 4 5 6 7 8 9
def projection(table: list, liste_champs: list) -> list: ''' Renvoie une table (liste de dictinonaires) des enregistrements de table ne contenant uniquement les champs appartenant à liste_champs. ''' table_proj = ... for enregistrement in ...: table_proj.append({c: v for c, v in ... if ... }) return ...
-
Utiliser cette fonction pour obtenir la table précédente.
3.2.3 Tri⚓︎
Trier une table selon un champ permet d'améliorer sa lisibilité selon l'information recherchée.
Spoiler-alert : Puisqu'une table est une liste, on pourrait utiliser les algorithmes étudiés au thème 7. Mais ceux-ci sont peu efficaces, comme on va le voir.
On va donc utiliser les fonctions natives de Python pour trier une liste: la méthode sort
et la fonction sorted
.
Différence fondamentale entre sort
et sorted
- La méthode
sort
trie en place, c'est-à-dire qu'elle modifie la liste à laquelle on applique la méthode et renvoieNone
:>>> l = [4, 0, 1, 3, 2] >>> a = l.sort() >>> l [0, 1, 2, 3, 4] >>> a >>>
- La fonction
sorted
ne modifie pas la liste mais crée une nouvelle liste:
>>> l = [4, 0, 1, 3, 2] >>> a = sorted(l) >>> a [0, 1, 2, 3, 4] >>> l [4, 0, 1, 3, 2]
Dans notre cas, on préfèrera ne pas modifier la table étudiée, mais plutôt créer une nouvelle table triée: on utilisera donc la fonction sorted
.
Ordre de tri
Par défaut le tri avec sorted
se fait dans l'ordre croissant. Si on veut un ordre décroissant, il suffit de passer un argument reverse
(un booléen) à la fonction:
>>> sorted([4, 0, 1, 3, 2], reverse=True)
[4, 3, 2, 1, 0]
Clé de tri
Par défaut:
- les objets de type
int
sont triés avec l'ordre usuel; - les objets de type
str
sont triés avec l'ordre alphabétique; - les objets de type
list
outuple
sont triés avec l'ordre lexicographique : on trie selon le premier élément, puis le deuxième, etc.1 2
>>> sorted([(2, 5), (1, 3), (1, 2), (2, 7), (1, 6), (0, 10), (3, 4), (2, 0)]) [(0, 10), (1, 2), (1, 3), (1, 6), (2, 0), (2, 5), (2, 7), (3, 4)]
Lorsqu'on souhaite trier des données différemment, il faut préciser une clé de tri: selon quel critére on veut trier. Cela sera particulièrement utile pour trier des dictionnaires...
Cette clé de tri doit impérativement être une fonction, que l'on précisera avec l'argument key
. En général on créera cette fonction pour l'occasion.
Pour trier la liste:
l = [(2, 5), (1, 3), (1, 2), (2, 7), (1, 6), (0, 10), (3, 4), (2, 0)]
>>> def cle_tri(t: tuple) -> int:
return t[1]
>>> sorted([(2, 5), (1, 3), (1, 2), (2, 7), (1, 6), (0, 10), (3, 4), (2, 0)], key=cle_tri)
[(2, 0), (1, 2), (1, 3), (3, 4), (2, 5), (1, 6), (2, 7), (0, 10)]
Python ne sait pas comparer des dictionnaires (peut-être tout simplement parce que cela n'a pas de sens). Il faut donc préciser sur quel champ comparer les données pour les trier.
Voici une table:
1 2 3 |
|
Pour la trier sur les notes obtenues en Informatique, il faut construire la fonction suivante:
def cle_tri(dico):
return dico['Info']
Puis on peut trier la table, en précisant par exemple l'ordre décroissant:
classement_info = sorted(releve, key=cle_tri, reverse=True)
On ne peut pas trier un dictionnaire (il n'est pas ordonné), mais on peut trier ses items()
qui sont une liste de tuple
de la forme (cle, valeur)
.
Donc par exemple si on veut trier les pokemons (voir l'exercice 3 ici on peut faire:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
>>> sorted(exemple_pokemons.items(), key=tri_nom)
[('Abo', (200, 7)), ('Bulbizarre', (70, 7)), ('Goupix', (60, 10)), ('Herbizarre', (100, 13)), ('Jungko', (170, 52)), ('Pikachu', (40, 6))]
>>> sorted(exemple_pokemons.items(), key=tri_longueur_nom)
[('Abo', (200, 7)), ('Jungko', (170, 52)), ('Goupix', (60, 10)), ('Pikachu', (40, 6)), ('Bulbizarre', (70, 7)), ('Herbizarre', (100, 13))]
>>> sorted(exemple_pokemons.items(), key=tri_taille)
[('Pikachu', (40, 6)), ('Goupix', (60, 10)), ('Bulbizarre', (70, 7)), ('Herbizarre', (100, 13)), ('Jungko', (170, 52)), ('Abo', (200, 7))]
>>> sorted(exemple_pokemons.items(), key=tri_poids)
[('Pikachu', (40, 6)), ('Bulbizarre', (70, 7)), ('Abo', (200, 7)), ('Goupix', (60, 10)), ('Herbizarre', (100, 13)), ('Jungko', (170, 52))]
>>>
Exercice 6
-
Trier la table
table_sw
selon le champ'Nom'
. -
Trier la table
table_sw
selon le champ'Espèce'
, puis le champ'Nom'
(rappel: Python sait trier des tuples).
-
c'est notamment le vocabulaire des bases de données, au programme de Terminale. ↩