Traitement de tables matricielles (tableur)
Introduction :
Les données organisées en tables structurent les informations individuelles qu’elles contiennent. Nous allons successivement aborder l’indexation de données, puis la recherche d’informations dans les tables. Nous aborderons ensuite le tri ainsi que la fusion de tables.
Indexation de tables
Indexation de tables
Avant de pouvoir effectuer des opérations de tri ou des recherches sur des données organisées en tables, nous devons accéder à ces données. Nous allons nous placer dans le cas de figure où les données ont été stockées sous forme tabulaire dans un fichier stocké dans le répertoire courant de notre ordinateur.
Données tabulaires
Données tabulaires
Données tabulaires :
Des données sont dites tabulaires, s’il est possible de les organiser en tables, c’est-à-dire en lignes et en colonnes où chaque type d’information est toujours placé au même endroit.
Les logiciels de type tableur sont des outils conçus pour manipuler des données tabulaires.
Le stockage de données tabulaires sous forme de fichiers peut s’effectuer avec différents formats ouverts ou propriétaires. Le format ouvert le plus connu est le format CSV. Un format propriétaire faisant souvent l’objet d’un brevet, nécessite un logiciel spécifique pour être lisible, contrairement à un format ouvert dont les spécifications techniques sont publiques avec un accès illimité aux données.
Format CSV
Format CSV
Le format CSV est au départ un format ouvert de fichier texte où les données sont séparées entre elles par une virgule. L’extension de fichier correspondante est .csv.
Le sigle CSV est l’abréviation de « Comma-Separated Values », soit en français valeurs séparées par des virgules.
Le fichier nommé
contient prénom, âge et taille des élèves. Il est structuré ainsi :Il est possible de générer un tel fichier avec un simple éditeur de texte. Les logiciels tableurs proposent également la possibilité d’exporter des données à ce format. La première ligne du fichier contient parfois les intitulés des données.
On observe que chaque ligne est agencée de la même manière, avec un retour à la ligne après chaque groupe de données. On remarque aussi que chaque type d’information est toujours au même endroit. Ainsi l’âge est toujours en deuxième position, après le prénom et avant la taille.
- L’emploi d’un séparateur permet de stocker des données individuelles de longueur variable plus efficacement qu’en imposant une longueur fixe pour chacune de ces données.
Le choix du séparateur est important : ce caractère ne doit jamais se retrouver dans les données elles-mêmes. Dans le cas contraire, une donnée comportant le caractère choisi comme séparateur sera vue comme deux données élémentaires.
Le format CSV ne répond pas à une spécification formelle très précise. Il en existe de nombreuses variantes, notamment avec le recours au signe « ; » (point-virgule), qui est moins susceptible d’entrer dans la composition des données élémentaires elles-mêmes, que la virgule ou le point. La virgule est en effet utilisée comme séparateur décimal et le point parfois comme séparateur de milliers. Les données peuvent aussi être séparées par des tabulations.
Acquisition de données tabulaires
Acquisition de données tabulaires
Prenons comme base le fichier nommé
, fourni en exemple ci-dessus. Nous allons écrire un programme Python qui va lire le contenu de ce fichier et nous permettre ensuite de manipuler les données qu'il contient.L’acquisition de données tabulaires est techniquement possible, sans recourir à aucun module spécialisé. Toutefois, cela nécessiterait de programmer soi-même la lecture du fichier et le traitement de chaque ligne, dont, notamment, le découpage des contenus sur la base du séparateur et la gestion des caractères d’échappement.
Les caractères d’échappement sont des caractères faisant partie de la syntaxe de beaucoup de langages de programmation et permettent de déclencher une interprétation alternative du ou des caractères qui le suivent.
La bibliothèque standard comporte un module dédié qui facilite grandement l’acquisition de données tabulaires. Ce module s’appelle csv.
- Il se mobilise par un simple import.
L’emploi du module csv, pour l’acquisition de données tabulaires contenues dans un fichier de notre répertoire courant, s’effectue ensuite de la manière suivante :
où
, et sont des noms de variables fixés par le programmeur.Ce code produit l’affichage suivant :
- On observe que chaque ligne lue par le lecteur fourni par le module csv (csv.reader) est une liste. Cette liste est composée de chacun des éléments individuels présents sur chaque ligne du fichier.
Quand les données sont séparées par des tabulations, le format est parfois appelé TSV (pour Tabulation-Separated Values). L’extension correspondante est .tsv. Mais en pratique, il arrive souvent que des fichiers dont les données sont séparées par des tabulations portent l’extension .csv. ou l’extension .txt. Le lecteur du module csv est capable de les importer correctement, à condition de lui préciser le délimiteur employé sous la forme
qui représente la tabulation.Stockage en mémoire de données tabulaires
Stockage en mémoire de données tabulaires
Les données lues par le module csv sont fournies sous forme de listes. Notre code précédent s’est contenté d’afficher les données en provenance du fichier source. Mais il serait plus commode de pouvoir y accéder à loisir pour effectuer des recherches ou des traitements.
Modifions donc notre code initial pour stocker l’ensemble des données dans une liste.
Vérifions le contenu de la variable eleves.
Produit l’affichage suivant :
Notre liste contient bien des sous-listes qui correspondent à chaque ligne du fichier .csv. Nous pouvons donc accéder aux données individuelles avec la notation indexée, en utilisant un double index : le premier désigne la ligne souhaitée, le second l’élément dans la ligne.
Nous pouvons ainsi afficher l’âge de Caroline de la manière suivante :
Au lieu de stocker les données lues depuis le fichier .csv en listes, nous aurions pu choisir de les stocker dans des tuples.
Vérifions le contenu de la variable eleves avec le recours aux tuples.
Produit l’affichage suivant :
Le choix de stocker les données en listes ou en tuples dépend des manipulations que l’on souhaite effectuer ensuite sur les données. Le caractère non mutable des tuples permet uniquement leur lecture. Nous pourrions toutefois ajouter ou supprimer des tuples au sein de la liste qui les contient. Les listes étant mutables, le stockage en liste de listes, autorise en revanche une éventuelle mise à jour des données individuelles.
Nous avons appris à intégrer des données provenant de fichiers externes. Nous allons maintenant aborder les possibilités de recherche au sein de ces données.
Recherche dans une table
Recherche dans une table
Pour découvrir les possibilités et les modalités de recherche au sein de données tabulaires, nous allons à nouveau nous appuyer sur un exemple.
Cette fois nous disposons d’une liste d’adhérents à une association d’initiation aux sciences numériques. Le prénom et le nom de chaque adhérent sont inclus, dans cet ordre, dans un tuple. L’ensemble des tuples est stocké dans une liste.
Recherche simple
Recherche simple
Nous souhaitons dans un premier temps vérifier si une personne prénommée « Lisa » figure parmi les adhérents.
Ce code produit l’affichage suivant :
Ce même algorithme fonctionne aussi quand plusieurs personnes portent le prénom recherché.
Ce code produit l’affichage suivant :
Dans le cas présent, le même prénom est porté par plusieurs personnes distinctes. Mais il arrive parfois que des données soient présentes à plusieurs reprises dans un ensemble de données, par exemple à la suite d’une erreur de double-saisie.
- Cette redondance s’appelle un doublon.
Doublon :
Information redondante dans un ensemble de données.
Nous avons jusqu’à présent recherché des chaînes de caractères exactes, mais nous pouvons modifier légèrement notre recherche pour obtenir la liste de tous les prénoms comportant celui de « Lisa ».
Ce code produit l’affichage suivant :
Nous allons maintenant effectuer des recherches un peu plus avancées.
Recherche avec connecteurs propositionnels
Recherche avec connecteurs propositionnels
Il est possible d’affiner nos recherches en combinant plusieurs critères grâce à des connecteurs propositionnels.
Connecteur logique propositionnel :
Un connecteur logique propositionnel relie entre elles des propositions simples.
Les connecteurs les plus courants sont « et » et « ou », exprimés par
et dans le langage Python.Effectuons d’abord une recherche simple sur les personnes dont le nom de famille est « Martin » pour connaitre le nombre de résultats correspondants.
Ce code produit l’affichage suivant :
Nous pouvons obtenir seulement la fiche de « Sarah Martin » en combinant nos critères de recherches avec le connecteur logique « et ».
Ce code produit l’affichage suivant :
Nous pouvons aussi élargir nos critères de recherche en employant le connecteur logique « ou ».
Ce code produit l’affichage suivant :
- Le connecteur ne porte pas nécessairement sur la même variable.
Richard est un prénom courant. C’est aussi un nom de famille très fréquent. Nous pouvons rechercher un adhérent dont le prénom ou le nom est « Richard » avec le code suivant :
Ce code produit l’affichage suivant :
Recherche avec opérateur d’appartenance
Recherche avec opérateur d’appartenance
L’emploi des connecteurs peut s’avérer fastidieux quand les éléments recherchés sont nombreux.
Nous voulons rechercher tous les adhérents nommés « Alice », « Lisa », « Sarah », ou « Paul ».
Au lieu d’écrire ceci :
Python nous permet d’écrire ceci pour une recherche équivalente :
Intégrons cette formulation dans notre algorithme de recherche :
Nous obtenons les résultats suivants :
Dans cette construction l’opérateur d’appartenance
remplace avantageusement l’enchaînement des connecteurs logiques .Nous pouvons également employer l’opérateur d’appartenance avec une négation
pour obtenir facilement tous les prénoms autres que ceux cités.Modifions notre instruction conditionnelle :
Nous obtenons l’affichage suivant :
Sans l’opérateur d’appartenance, il nous faudrait formuler la condition ainsi :
ou encore ainsi :
- L’opérateur d’appartenance peut se révéler utile pour conserver un code lisible avec certaines recherches multi-critères.
La fiabilité de nos recherches repose sur la bonne construction de nos propositions et leur bonne articulation logique le cas échéant. Mais elle dépend aussi de la qualité et la cohérence des données.
Cohérence et normalisation des données
Cohérence et normalisation des données
La cohérence des données est importante car elle conditionne la qualité des recherches et des traitements qui peuvent être effectués ensuite.
En général, on s’attache à valider la cohérence des données dès la saisie.
- Un formulaire de saisie de données peut imposer l’entrée de valeurs strictement numériques, pour un âge ou pour un code postal français. Certaines rubriques peuvent être rendues obligatoires selon les besoins pour valider la saisie des données, comme la saisie d’un nom et d’un prénom, ou encore d’une adresse de courrier électronique.
- Les tests de cohérence peuvent également limiter les valeurs permises, avec par exemple un âge positif et ne pouvant dépasser la longévité humaine, ou encore un nombre composé impérativement de cinq chiffres pour un code postal français.
En l’absence de garanties sur la cohérence à la source des données acquises, il sera nécessaire d’inclure des vérifications ou des transformations préalables pour pouvoir travailler sur les données.
Il arrive fréquemment qu’un fichier contienne des noms de personnes ou de lieux, saisis sans cohérence entre minuscules et majuscules. « Martin », « martin » et « MARTIN » sont peut-être la même personne pour un humain, mais pour un ordinateur ce sont trois chaînes de caractères distinctes.
Dans ce cas, on choisira d’effectuer une normalisation préalable des données, par exemple en convertissant au choix toutes les chaînes de caractères en majuscules, ou en minuscules, ou avec la première lettre en majuscule et le reste en minuscules.
Cette étape préalable permet d’effectuer des recherches simples où il suffit de formater l’élément recherché à l’identique de la normalisation appliquée aux données.
Sans cette normalisation, les expressions logiques de recherche seraient laborieuses à implémenter.
Dans l’exemple ci-dessus, il faudrait écrire :
C’est non seulement laborieux, mais il serait difficile de prévoir tous les cas de figure. Ainsi, le prénom écrit « marTin » ou « martiN » ne serait pas trouvé.
De même, une entrée sous la forme « Martin » (le prénom suivi d’un espace) ne serait pas trouvée. C’est pourquoi les éventuels caractères de type espace présents en début ou en fin de chaîne sont généralement supprimés systématiquement dans le cadre d’une normalisation. Des opérations complémentaires spécifiques peuvent être appliquées en fonction du profil des données d’origine.
Nous allons maintenant aborder les opérations de tri sur les données tabulaires ainsi que les fusions de données tabulaires d’ensembles distincts.
Tri et fusion de tables
Tri et fusion de tables
Pour cette partie nous reprenons les données sur les élèves, composées de leur nom, leur âge et leur taille.
Tri
Tri
Les fonctionnalités de tri permettent de réorganiser des ensembles de données tabulaires selon différents critères, à des fins de traitements ou de présentation de ces données.
Python propose deux solutions de tri :
- Le tri sur place avec la méthode qui effectue un tri en place et ne retourne rien, c’est-à-dire modifie directement la liste passée en argument ;
- Le tri avec la fonction qui retourne une nouvelle liste triée à partir de la liste passée en argument.
Pour nos besoins nous allons utiliser
qui ne modifie pas la liste de données passée en argument. Nous pourrons ainsi constater l’effet de tris distincts effectués sur une base inchangée, celle de la liste nommée « eleves ».Nous afficherons chaque fois la liste retournée par la fonction, que nous pourrions aussi stocker dans une nouvelle variable si nécessaire.
Dans son cas d’usage le plus simple, la fonction
prend en argument la liste qu’on souhaite trier.Nous obtenons une liste de listes triées par ordre croissant selon le premier champ de donnée, puis le second et le troisième, de manière ascendante. Le tri se fait sur les éléments successifs de chaque sous-liste, de la même manière qu’un dictionnaire ordonne les mots sur la base des lettres successives composant le mot.
Un paramètre optionnel de la fonction
permet de trier facilement la liste en ordre inverse.La fonction
dispose aussi d’un paramètre key qui permet de spécifier une clé de tri pour personnaliser l’ordre dans lequel les données sont triées.- La clé de tri est une fonction quelconque, native ou créée par l’utilisateur.
Nous allons créer une fonction qui retourne le second élément d’une liste donnée, et utiliser cette fonction comme critère de tri de notre liste.
Le tri de la liste a bien été effectué par ordre croissant de la seconde donnée, c’est-à-dire à l’âge des élèves.
Vous noterez l’absence de parenthèse après
car il ne s’agit pas d’un appel à la fonction. C’est la fonction elle-même qui est passée comme argument au paramètre key.Le tri a porté sur l’âge, mais les tailles pour un même âge ne sont pas nécessairement dans l’ordre. Corrigeons cela avec une nouvelle fonction de tri personnalisée prenant en compte les deux critères.
Le tri a bien porté d’abord sur l’âge, puis sur la taille.
- Voyons maintenant comment nous pouvons trier la liste par ordre décroissant de longueur des prénoms. On définit une fonction qui retourne la longueur du premier élément à partir d’une liste.
Cette fonction devient notre nouveau critère de tri personnalisé :
Le tri peut donc être grandement personnalisé en fonction des besoins, ceci grâce à la fonction de tri que l’on peut lui associer. Abordons maintenant la fusion de données tabulaires.
Fusion de tables
Fusion de tables
Des données réparties dans plusieurs ensembles distincts peuvent être réunies pour former un ensemble complet et unique.
Nous disposons d’une liste d’élèves dont nous connaissons les prénoms, les âges et les tailles et nous souhaitons rapprocher ces données d’une autre liste qui contient leurs noms complets.
Pour pouvoir rapprocher ces deux listes et les fusionner, nous devons déterminer un critère sur lequel les réunir. Dans le cas présent nous allons utiliser le prénom. Nous recherchons dans la seconde liste les informations associées au prénom trouvé dans la première liste pour pouvoir y associer les données correspondantes. Nous stockons l’ensemble dans une nouvelle liste.
On obtient l’affichage suivant :
Selon la manière dont les informations sont agencées et le type d’information à réunir, certaines difficultés peuvent se présenter.
La présence de doublons ou l’absence d’entrée en correspondance sur le critère de fusion seraient de nature à poser un problème. Cela se traduirait dans l’exemple précédent par un prénom qui n’est pas commun aux deux listes ou, à l’inverse, un prénom qui se trouve dupliqué dans l’unes des deux listes.
C’est pourquoi, il faut penser à traiter les problèmes de doublons et bien prendre en compte le domaine de valeurs de l’élément servant au rapprochement, c’est-à-dire l’ensemble des valeurs possibles pour cet élément.
Quand des valeurs sont manquantes dans le cadre d’une fusion, il est préférable de le mentionner explicitement. Différentes codifications peuvent être employées pour représenter des données manquantes :
- L’objet Python exprime l’absence de valeur ;
- L’identifiant « NA » pour « Not Available » (« Non Disponible » en français) est fréquemment employé par différents logiciels et peut figurer dans un fichier de type .csv.
La fusion de données et le traitement de données nominatives sont strictement encadrés juridiquement. On se référera aux dispositions du règlement européen sur la protection des données (R.G.P.D.), consultable sur le site de la Commission Nationale de l’Informatique et des Libertés.
Conclusion :
La structuration des informations en données tabulaires permet de réaliser un certain nombre de traitements. Nous avons d’abord étudié leur indexation puis les différentes recherches que l’on peut y pratiquer, selon des critères simples ou articulés en logique propositionnelle.
Nous avons ensuite découvert différentes manières de trier ces données, ainsi que la possibilité de fusionner des données tabulaires provenant d’ensembles distincts.