Skip to content

Traitement de données en tables

Objectifs

L'objectif de ce cours est d'aborder la notion de traitement de données en table.

Ce cours permet d'introduire la notion de base de données qui sera abordée en terminale.

En effet avec l'introduction du modèle relationnel (notion que vous aborderez en terminale), les tables de données, stockées dans des bases de données, sont le principal moyen de stocker de l'information structurée.

Exemples (du quotidien) de données en tables :

  • relevés de compte bancaire ;
  • relevés de note d'une classe ;
  • etc....

Ce cours va décrire les manipulations qu'il est possible de réaliser depuis un langage de programmation (ici Python) sur les données en tables (autrement nommées données tabulées).

Une fois chargées, ces données en tables seront manipuler sous la forme de données structurées :

  • tableau de tableaux ;
  • tableau de dictionnaires.

Ce cours portera principalement sur les données issues d'une association canine.

Remarque

Dans ce cours, on fait volontairement le choix d'utiliser d'ores et déjà le vocabulaire que vous utiliserez dans le cours portant sur les bases de données.

Données tabulées et fichier CSV

Notion de table

Définition

Le stockage de données sous forme tabulaire (sous forme de tableaux également appelés tables) est très utilisé dans le domaine de l'informatique.

Prenons pour exemple la table représentative de l'ensemble des chiens présents dans une association canine :

id_tatouage nom annee_naissance sexe race
172frg Smoothie 2016 f Berger_australien
349jad Cassoulet 2015 m Caniche
523chu Basta 2016 f Beagle
472koa Némo 2017 m Berger_australien

De nombreux logiciels, tels que le logiciel LibreOffice Calc, permettent de manipuler des données stockées sous la forme de tables :

Exemple :

Tableur LibreOfficeCalc

Important

Une table a systématiquement les propriétés suivantes :

  • Une table regroupe un ensemble d'éléments de même nature ;
  • Une ligne de la table correspond un de ces éléments (on parle aussi d'entité unique ou d'enregistrements) ;
  • Les colonnes représentent les attributs (également appelés champs) communs à l'ensemble des éléments présents dans la table.
  • Les valeurs d'un attribut donné de la table sont toutes du même type (chaîne de caractères, nombre entier, flottant...)

Par exemple, dans la table ci-dessus :

  • La table regroupe l'ensemble des chiens présents dans une association canine ;
  • Chaque ligne correspond à un chien particulier présent dans l'association canine ;
  • Les attributs communs à l'ensemble des chiens sont : id_tatouage, nom, annee_naissance, sexe, race.
  • Pour exemple, l'attribut annee_naissance est de type entier.

Fichier CSV

Définition

Pour échanger des données tabulées on a souvent recours à des fichiers au format CSV (de l'anglais "Comma Separated Values" qui signifie données séparées par des virgules).

Voici, pour exemple, le contenu d'un fichier CSV assos_canine.csv comportant l'ensemble des chiens présents dans l'association canine :

"id_tatouage","nom","annee_naissance","sexe","race"
"172frg","Smoothie",2016,"f","Berger_australien"
"349jad","Cassoulet",2015,"m","Caniche"
"523chu","Basta",2016,"f","Beagle"
"472koa","Némo",2017,"m","Berger_australien"

Définition

Un fichier CSV est un fichier texte (avec .csv pour extension) dans lequel chaque ligne du fichier correspond à une ligne de la table à stocker.

Chaque ligne du fichier CSV est composée d'un même nombre de champs séparés par une virgule , (ou par un point-virgule ; ou par autres séparateurs tels que la tabulation).

Des guillemets " " peuvent parfois être utilisés pour délimiter le contenu des champs.

Souvent, la première ligne du fichier CSV, nommée ligne d'entête, correspond à l'intitulé des attributs (des champs).

Par exemple, dans le fichier assos_canine.csv :

  • la ligne 1 spécifie le nom des attributs ;
  • la colonne 1 a id_tatouage comme nom d'attribut ;
  • la ligne 2 est représentative du chien dont le numéro de tatouage est "172frg".

Le logiciel LibreOffice Calc permet l'enregistrement des données tabulées sous la forme d'un fichier CSV et propose alors le choix :

  • du type d'encodage des caractères (UTF-8, etc) ;
  • du caractère séparateur de champ ("," ";" etc) ;
  • du caractère délimitant le contenu des champs.

Enregistrement fichier CSV

Remarque

Dans un fichier CSV, toutes les lignes doivent avoir le même nombre de champs. Si un champ est vide la présence des caractères séparateurs s'avère donc obligatoire.

Exemple :

"id_tatouage","nom","annee_naissance","sexe","race"
"172frg","Smoothie",2016,"f","Berger_australien"
"349jad","Cassoulet",,"m","Caniche"

Le format CSV n'a cependant jamais vraiment fait l'objet d'une spécification formelle. Ce format est toutefois assez populaire parce qu'il est facile à générer et à manipuler.

De nombreux sites Internet proposent des données sous la forme de fichiers CSV, on peut notamment citer le site de l'éducation nationale :

https://data.education.gouv.fr/pages/accueil/

Ouverture d'un fichier CSV en Python

Définition

La bibliothèque Python dispose du module CSV dont les fonctions permettent de lire et d'écrire des fichiers CSV.

Exemple : Chargement sous la forme d'un tableau de tableaux

Pour exemple, le programme ci-dessous permet de charger en mémoire l'ensemble des données contenues dans le fichier assos_canine.csv et d'y associer la variable table (le fichier CSV à lire est ici à placer dans le même dossier que le fichier Python).

1
2
3
4
5
import csv
fichier = open("assos_canine.csv", 'r', encoding="utf-8")
table = list(csv.reader(fichier, delimiter=','))
print(table)
fichier.close()

La variable table est alors un tableau de tableaux de chaînes de caractères :

[['id_tatouage', 'nom', 'annee_naissance', 'sexe', 'race'],
 ['172frg', 'Smoothie', '2016', 'f', 'Berger_australien'],
 ['349jad', 'Cassoulet', '2015', 'm', 'Caniche'],
 ['523chu', 'Basta', '2016', 'f', 'Beagle'],
 ['472koa', 'Némo', '2017', 'm', 'Berger_australien']]
  • Le code ci-dessus permet l'ouverture du fichier assos_canine.csv en lecture seule 'r' selon l'encodage utf-8 ;
  • L'objet fichier va ici permettre d'effectuer des opérations de lecture sur le fichier assos_canine.csv.
  • csv.reader(fichier, delimiter=',') renvoie un itérateur associé à l'ensemble des lignes présentes dans le fichier CSV (chaque ligne lue depuis le fichier CSV est renvoyée comme un tableau de chaînes de caractères).
  • Le constructeur list permet l'obtention d'un tableau comportant les tableaux de chaînes de caractères associés à chaque ligne.

L'accès à la race du chien Basta est donc ainsi réalisé ainsi :

print(table[3][4])
>>> Beagle

Exemple : Chargement sous la forme d'un tableau de dictionnaires

La solution précédente présente des inconvénients :

Structure de données précédentes
[['id_tatouage', 'nom', 'annee_naissance', 'sexe', 'race'],
 ['172frg', 'Smoothie', '2016', 'f', 'Berger_australien'],
 ['349jad', 'Cassoulet', '2015', 'm', 'Caniche'],
 ['523chu', 'Basta', '2016', 'f', 'Beagle'],
 ['472koa', 'Némo', '2017', 'm', 'Berger_australien']]
  • La première ligne, celle de l'intitulé des attributs a été chargée comme une ligne de données (qu'il convient d'ignorer lors du traitement des données) ;
  • Chaque ligne est représentée sous la forme d'un tableau ce qui nécessite de se souvenir de l'indice associé à chaque intitulé d'attributs... ;
  • Toutes les données ont été converties en chaînes de caractères.

Pour ces raisons on préférera le code python suivant :

1
2
3
4
5
import csv
fichier = open("assos_canine.csv", 'r', encoding="utf-8")
table = list(csv.DictReader(fichier, delimiter=','))
print(table)
fichier.close()

L'appel de la fonction DictReader permet ici d'associer la variable table à un tableau de dictionnaires :

[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

Les intitulés des attributs présents dans la ligne d'entête ont été utilisés pour créer les clés des dictionnaires.

Ici l'accès à la race du chien Basta est plus aisé :

print(table[2]['race'])
>>> Beagle

Une fois le traitement terminé, il convient de fermer le fichier avec la méthode close() de l'objet fichier afin d'éviter tout conflit dans l'accès au fichier CSV.

Warning

On préférera souvent le code suivant :

1
2
3
import csv
with open("assos_canine.csv",'r',encoding="utf-8") as fichier:
    table = list(csv.DictReader(fichier, delimiter=','))

Ici la ligne with open("assos_canine.csv",'r',encoding="utf-8") as fichier: permet de limiter la validité de l'objet fichier au bloc indenté immédiatement en dessous. Au-delà de ce bloc, le fichier n'est plus ouvert.

Traitement simple de données en table

On rappelle que les données sont stockées dans un tableau de dictionnaires table de la manière suivante :

[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

Définition

Il est alors possible d'exploiter ces données via un programme Python afin de par exemple :

  • rechercher la présence d'une donnée ;
  • ou de récupérer la valeur d'une donnée souhaitée.

On va chercher ici à "interroger" la structure de données afin de rechercher ou de récupérer des données.

Dans le cas des bases de données, on dit que l'on interroge la base de données à l'aide de requêtes.

Recherche de la présence d'une donnée

Exemple

On souhaite ici rechercher la présence d'une donnée dans la table.

On recherche ici si un chien, dont on connaît le nom, est présent ou non dans l'association canine.

1
2
3
4
5
6
7
def recherche_nom(t, valeur_nom):
    for dico in t:
        if dico["nom"] == valeur_nom:
            return True
    return False

print(recherche_nom(table, "Smoothie"))
Rappel de la structure de données utilisée
[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

La fonction recherche_nom reçoit en paramètres la table et le nom du chien à rechercher dans la table.

Cette fonction recherche_nom renvoie alors :

  • True si le nom de chien est présent dans la table ;
  • False dans le cas contraire.

Récupération d'une donnée

Exemple

On souhaite ici récupérer la valeur d'une donnée présente dans la table.

Plus précisément, on souhaite ici récupérer le nom du chien pour lequel on connaît le numéro de tatouage.

1
2
3
4
5
6
7
def recuperation_nom(t, valeur_idtatouage):
    for dico in t:
        if dico["id_tatouage"] == valeur_idtatouage:
            return dico["nom"]
    return None

print(recuperation_nom(table, "349jad"))
Rappel de la structure de données utilisée
[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

La fonction recuperation_nom reçoit en paramètres la table et la valeur de l'identifiant de tatouage du chien dont on souhaite connaître ici le nom.

La fonction renvoie :

  • le nom du chien si l'identifiant est présent ;
  • None dans le cas contraire.

Important

Ici le critère de recherche id_tatouage est unique pour chaque ligne de la table.

Dans le cas des bases de données relationnelles, on parlera de clef primaire.

Traitement avancé de données en tables

Définition

Il est parfois nécessaire d'extraire de la table d'origine un ensemble de données sous la forme d'une nouvelle table (donc ici d'un nouveau tableau de dictionnaires).

Sélection

Important

L'opération de sélection consiste à construire une nouvelle table en extrayant de la table d'origine toutes les lignes vérifiant une condition (sélection de certaines lignes).

Exemple

On souhaite extraire de la table suivante les entités correspondantes à des chiens mâles :

[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

On souhaiterait obtenir la table suivante :

[{'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

Le code ci-dessous permet par exemple de construire une nouvelle table comportant uniquement des lignes (des éléments) associées aux chiens mâles.

1
2
3
4
table2 = []
for d in table:
    if d["sexe"] == "m":
        table2.append(d)

Il est très pertinent ici d'utiliser le principe de construction de tableau en compréhension. Le code précédent est donc équivalent à :

1
table2 = [dico for dico in table if dico["sexe"]=="m"]

Lien avec le langage SQL

L'écriture en compréhension précédente est relativement proche de l'écriture du langage SQL qui vous permettra d'interagir avec les données présentes dans une base de données :

SELECT * FROM table WHERE sexe = "m";

Projection

Important

L'opération de projection consiste à construire une nouvelle table constituée d'une partie des colonnes (des attributs) présentes dans la table d'origine (sélection de certaines colonnes).

Exemple

On souhaite construire une nouvelle table constituée des colonnes nom et race à partir de la table suivante :

[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

On souhaiterait donc obtenir la table suivante :

[{'nom': 'Smoothie', 'race': 'Berger_australien'},
 {'nom': 'Cassoulet', 'race': 'Caniche'},
 {'nom': 'Smoothie', 'race': 'Beagle'},
 {'nom': 'Némo', 'race': 'Berger_australien'}]

En Python, la projection sur les colonnes nom et race de la table d'origine consiste à construire un nouveau dictionnaire constitué des attributs (clés du dictionnaire) nom et race :

1
table2 = [{"nom": dico["nom"], "race": dico["race"]} for dico in table]

Lien avec le langage SQL

L'écriture en compréhension précédente est relativement proche de l'écriture du langage SQL qui vous permettra d'interagir avec les données présentes dans une base de données :

SELECT nom, race FROM table;
Autre écriture possible
1
2
3
table2 = []
for dico in table:
    table2.append({"nom": dico["nom"], "race": dico["race"]})

Sélection et projection

Définition

Il est évidemment possible d'extraire des données de la table d'origine en cumulant les effets des opérations de sélection et de projection.

Exemple

On souhaite construire une nouvelle table constituée du nom et de la race des chiens mâles présents dans l'association canine à partir de la table suivante :

[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]

On souhaiterait donc obtenir la table suivante :

[{'nom': 'Cassoulet', 'race': 'Caniche'},
 {'nom': 'Némo', 'race': 'Berger_australien'}]

En Python, la projection sur les colonnes nom et race et la sélection des entités correspondant à des chiens mâles à partir de la table d'origine consiste à construire un nouveau dictionnaire constitué des attributs (clés du dictionnaire) nom et race pour lesquels les chiens sont des mâles :

1
table2 = [{"nom": dico["nom"], "race": dico["race"]} for dico in table if dico["sexe"]=="m"]

Lien avec le langage SQL

L'écriture en compréhension précédente est relativement proche de l'écriture du langage SQL qui vous permettra d'interagir avec les données présentes dans une base de données :

SELECT nom, race FROM table WHERE sexe = "m";
Autre écriture possible
1
2
3
4
table2 = []
for dico in table:
    if dico["sexe"] == "m":
        table2.append({"nom": dico["nom"], "race": dico["race"]})

Obtention de données valides en vue de leur traitement

Important

Il est important de constater que dans la table d'origine (issue du fichier CSV) toutes les données sont des chaînes de caractères, même les années de naissance de chien ce qui rend impossible tous calculs (age, age moyen, etc...)

Pour résoudre cette impossibilité, on va mettre en place la fonction conversion_annee recevant en paramètre un dictionnaire de notre table et renvoyant un nouveau dictionnaire dans lequel la valeur associée à la clé annee_naissance est un entier.

Exemple

On construit alors en compréhension une nouvelle table table_valide comportant une valeur d'année de naissance de type entier pour chaque dictionnaire.

Rappel de la structure de données utilisée
[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Berger_australien'},
 {'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': '2015', 'sexe': 'm', 'race': 'Caniche'},
 {'id_tatouage': '523chu', 'nom': 'Basta', 'annee_naissance': '2016', 'sexe': 'f', 'race': 'Beagle'},
 {'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': '2017', 'sexe': 'm', 'race': 'Berger_australien'}]
1
2
3
4
5
6
def conversion_annee(d):
    entier = int(d["annee_naissance"])
    return {"id_tatouage": d["id_tatouage"], "nom": d["nom"], "annee_naissance": entier, "sexe": d["sexe"], "race": d["race"]}

table_valide = [conversion_annee(dico) for dico in table]
print(table_valide)
[{'id_tatouage': '172frg', 'nom': 'Smoothie', 'annee_naissance': 2016, 'sexe': 'f', 'race': 'Berger_australien'},
{'id_tatouage': '349jad', 'nom': 'Cassoulet', 'annee_naissance': 2015, 'sexe': 'm', 'race': 'Caniche'},
{'id_tatouage': '523chu', 'nom': 'Smoothie', 'annee_naissance': 2016, 'sexe': 'f', 'race': 'Beagle'},
{'id_tatouage': '472koa', 'nom': 'Némo', 'annee_naissance': 2017, 'sexe': 'm', 'race': 'Berger_australien'}]

Agrégation

Important

Les opérations d'agrégation portent sur plusieurs lignes de la table dans le but de produire un résultat unique relatif à ces lignes.

Exemple :

  • Nombre d'occurrences à l'issue d'une sélection ;
  • Moyenne des valeurs d'un attribut sur une sélection de lignes données ;
  • ...

Exemple

Par exemple, la fonction nombre_chiens_males renvoie le nombre de chiens mâles présents dans l'association canine :

1
print(nombre_chiens_males(table_valide))
2
Solution
1
2
3
4
5
6
7
8
def nombre_chiens_males(t):
    nb = 0
    for dico in t:
        if dico["sexe"] == "m":
            nb += 1
    return nb

print(nombre_chiens_males(table_valide))

Exemple

Autre exemple, la fonction age_max retourne l'âge du plus vieux chien présent dans l'association canine :

1
print(age_max(table_valide))
6
Solution
1
2
3
4
5
6
7
8
9
def age_max(t):
    a_max = 0
    for dico in t:
        age = 2021 - dico["annee_naissance"]
        if age > a_max:
            a_max = age
    return a_max

print(age_max(table_valide))

Important

Il est évidemment possible de sélectionner uniquement certaines lignes et de ne réaliser l'opération d'agrégation que pour les lignes ainsi sélectionnées.