Quelques pistes pour travailler le programme officiel NSI à partir de Python

3 - Traitement de données en table

Etienne Lozes -- Pâques 2019

3.1 Indexation de table

Au départ il nous faut un fichier texte csv qui contient des données, supposons que cela soit le fichier election.csv ci-dessous

nom,prenom,nb_voix

dupond,emile,514

dupont,chloe,632

dupons,camille,421

On peut charger le fichier dans un tableau à 2 dimensions

In [ ]:
import csv
with open('elections.csv') as fichier_csv :
    table = list(csv.reader(fichier_csv, delimiter=','))

ce qui aura pour effet de mettre dans la variable table

In [2]:
table = [['nom', 'prenom', 'nb_voix'], ['dupond', 'emile', '514'], ['dupont', 'chloe', '632'], ['dupons', 'camille', '421']]
table
Out[2]:
[['nom', 'prenom', 'nb_voix'],
 ['dupond', 'emile', '514'],
 ['dupont', 'chloe', '632'],
 ['dupons', 'camille', '421']]

on peut aussi charger le fichier csv sous forme d'une liste de dictionnaires; dans ce cas la première ligne du fichier permet de déterminer les clés

In [ ]:
with open('elections.csv') as fichier_csv :
    table = list(csv.DictReader(fichier_csv))

ce qui aura pour effet de mettre dans la variable table (à peu de choses près, car le csv.DictReader renvoie un dictionnaire dans lequel les clés sont ordonnées, mais ce n'est pas important pour nous ici)

In [4]:
table2 = [{'nom':'dupond','prenom':'emile','nb_voix':'514'},{'nom':'dupont','prenom':'chloe','nb_voix':'632'},{'nom':'dupons','prenom':'camille','nb_voix':'421'}]
In [5]:
table2
Out[5]:
[{'nom': 'dupond', 'prenom': 'emile', 'nb_voix': '514'},
 {'nom': 'dupont', 'prenom': 'chloe', 'nb_voix': '632'},
 {'nom': 'dupons', 'prenom': 'camille', 'nb_voix': '421'}]

Il ne faut pas oublier de convertir la colonne nb_voix en des entiers

In [6]:
for ligne in table2 : ligne['nb_voix'] = int(ligne['nb_voix'])
table2
Out[6]:
[{'nom': 'dupond', 'prenom': 'emile', 'nb_voix': 514},
 {'nom': 'dupont', 'prenom': 'chloe', 'nb_voix': 632},
 {'nom': 'dupons', 'prenom': 'camille', 'nb_voix': 421}]

3.2 Recherche dans une table

Supposons qu'on cherche la liste des lignes dans lesquelles le prénom commence par un c et le nombre de voix est supérieur à 300. On écrira

In [7]:
def bonne(ligne) : return ligne['prenom'][0] == 'c' and ligne['nb_voix'] > 300
list(filter(bonne, table2))
Out[7]:
[{'nom': 'dupont', 'prenom': 'chloe', 'nb_voix': 632},
 {'nom': 'dupons', 'prenom': 'camille', 'nb_voix': 421}]

On peut éviter de créer la fonction bonne et utiliser à la place une fonction anonyme (un "lambda")

In [8]:
list(filter(lambda ligne : ligne['nom'][-1] =='d' or ligne['nb_voix'] < 500, table2))
Out[8]:
[{'nom': 'dupond', 'prenom': 'emile', 'nb_voix': 514},
 {'nom': 'dupons', 'prenom': 'camille', 'nb_voix': 421}]

3.3 Trier une table suivant une colonne

On peut utiliser la méthode sort ou la fonction sorted qui permettent de trier une liste, en ajoutant un calcul de la clé utilisée pour comparer (sorted me permet de ne pas modifier ma table de départ et d'en construire une nouvelle).

Par exemple, si je veux trier par nombre de voix croissant

In [9]:
def nombre_voix(ligne) : return ligne['nb_voix']
sorted(table2, key=nombre_voix)
Out[9]:
[{'nom': 'dupons', 'prenom': 'camille', 'nb_voix': 421},
 {'nom': 'dupond', 'prenom': 'emile', 'nb_voix': 514},
 {'nom': 'dupont', 'prenom': 'chloe', 'nb_voix': 632}]

A nouveau j'ai parfois intérêt à utiliser une fonction anonyme pour ne pas créer de une fonction à chaque fois

In [10]:
sorted(table2, key=lambda ligne:ligne['nom'], reverse=True)
Out[10]:
[{'nom': 'dupont', 'prenom': 'chloe', 'nb_voix': 632},
 {'nom': 'dupons', 'prenom': 'camille', 'nb_voix': 421},
 {'nom': 'dupond', 'prenom': 'emile', 'nb_voix': 514}]

3.3 Fusion de deux tables

Un premier exemple de fusion est la concaténation verticale de deux tables ayant les même colonnes. Cela correspond à concaténer les deux listes

In [11]:
table1 = [{'nom':'dupont','prenom':'chloe'}]
table2 = [{'nom': 'dupons', 'prenom': 'camille'},
 {'nom': 'dupond', 'prenom': 'emile'}]
table_fusion = table1 + table2
table_fusion
Out[11]:
[{'nom': 'dupont', 'prenom': 'chloe'},
 {'nom': 'dupons', 'prenom': 'camille'},
 {'nom': 'dupond', 'prenom': 'emile'}]

Un deuxième exemple de fusion est la "concaténation horizontale" de deux tables n'ayant pas les mêmes colonnes. On peut supposer qu'au moins une colonne est commune aux deux, et qu'on a trié par rapport à cette colonne dans chacune des deux tables, de sorte que la ième ligne de la première table doit bien être associée à la ième ligne de la deuxième table.

In [12]:
table1 = [{'nom':'dupont','prenom':'chloe'},{'nom': 'dupons', 'prenom': 'camille'},{'nom':'dupond','prenom':'emile'}]
table2 = [{'nom':'dupont','nb_voix':632},{'nom': 'dupons', 'nb_voix': 514},{'nom':'dupond','nb_voix':421}]
table_fusion = [{**table1[i], **table2[i]} for i in range(len(table1))]
table_fusion
Out[12]:
[{'nom': 'dupont', 'prenom': 'chloe', 'nb_voix': 632},
 {'nom': 'dupons', 'prenom': 'camille', 'nb_voix': 514},
 {'nom': 'dupond', 'prenom': 'emile', 'nb_voix': 421}]