CSV or not CSV - 5 décembre 2023
Auteurice : Elsa Van Kote
Temps de lecture : ~6 minutes
L’objectif
Notre but est de se baser sur un fichier csv comportant des titres d’articles ainsi qu’un abstract de ces derniers. Ce fichier est un export csv d’une bibliothèque zotero.
On souhaite, afin de pouvoir faire de la visualisation sur une carte, ajouter une métadonnée initialement non présente qui est le lieu où se passe le fait relaté par l’article, et ceci dans une autre colonne du tableau.
En résumé, passer de :
Titre | Abstract |
---|---|
Au Mali et au Burkina Faso : la diplomatie de Macron « nous met en danger » | Alors que les députés débattent mardi de la politique africaine de la France, deux collectifs de ressortissants français du Mali et du Burkina Faso font entendre leur voix. Très critiques vis-à-vis d… |
à
Titre | Abstract | Lieux |
---|---|---|
Au Mali et au Burkina Faso : la diplomatie de Macron « nous met en danger » | Alors que les députés débattent mardi de la politique africaine de la France, deux collectifs de ressortissants français du Mali et du Burkina Faso font entendre leur voix. Très critiques vis-à-vis d… | Burkina Faso, Mali |
Le corpus étant de plusieurs centaines d’articles, on aimerait éviter de tout se farcir à la main…
Les étapes
Voici les différentes étapes à suivre :
- n’extraire que les deux colonnes du fichier.csv qui nous intéresse
- voir si des lieux cités dans le titre et l’abstract correspondent aux lieux d’un référentiel déjà existant
- ajouter les villes dans cette nouvelle colonne quand c’est le cas
La recette
Dans les différentes commandes qui vont suivre, le pipe sera traduit en commentaire par un PUIS.
- Première étape : savoir quels sont les numéros de colonnes qui nous intéresse dans notre csv :
(on ne sélectionne que la première ligne du fichier
puis on remplace les virgules par des sauts de ligne
puis on affiche les numéros de ligne)
head -n1 fichier.csv | tr ',', '\n' | nl
Dans notre cas, il s’agit des colonnes 5 et 11.
- Deuxième étape : récupérer les colonnes 5 et 11 du tableau :
(on coupe le tableau pour garder uniquement les colonnes 5 et 11
en prenant en compte que le délimiteur des colonnes est à chaque fois une virgule)
cut -d, -f5,11 fichier.csv
Et ici on voit qu’apparaît un problème : cette commande mélange les virgules de délimitation des colonnes et les virgules présentes dans le texte lui même, ce qui rend la sortie chaotique.
La solution est de transformer son fichier.csv en fichier.tsv qui ne prend pas les virgules comme délimiteurs, mais les tabulations.
- Troisième étape : on transforme son fichier.csv en fichier.tsv :
(on substitue les passages “,” qui représentent les délimiteurs de colonne pour les transformer en tabulation
puis on met la sortie dans un fichier nommé fichier.tsv)
Pour insérer une tabulation à l’intérieur d’un terminal, il faut d’abord appuyer sur Ctrl+V puis ensuite appuyer sur la touche souhaitée. Cela vaut pour d’autres caractères comme le retour à la ligne \n par exemple.
sed 's/","/ /g' fichier.csv > fichier.tsv
- Quatrième étape : on nettoie les derniers restes de présence du caractère “ présent en début et fin de ligne :
(on donne le fichier.tsv en stdin et on supprime les caractères souhaités)
< Afrique.tsv tr -d '"'
- Cinquième étape : maintenant que l’on a un fichier.tsv tout propre, on va pouvoir refaire l’étape numéro 2 qui ne fonctionnait pas avec le csv.
(on coupe le tableau pour garder uniquement les colonnes 5 et 11
plus besoin de mettre -d en argument de cut car par convention, il prend une tabulation comme délimiteur
on met la stdout dans un fichier.tsv)
cut -f5,11 fichier.tsv > fichier_avec_lieux.tsv
Deuxième partie
Dans cette partie on va devoir créer/récupérer un référentiel des viles du monde afin de pouvoir trouver des concordances avec les villes citées dans le titre et l’abstract. Pour cet exercice nous avons créé nous même un petit fichier avec une liste de noms présents ou non dans notre fichier.tsv, juste pour comprendre le mécanisme. Dans la pratique finale il serait bien de récupérer une base de données des villes déjà existantes.
Quelques questions d’un ordre cette fois scientifique se sont posées à nous : - y’a t-il des titres et abstracts en anglais ? si oui, cela va poser un problème dans la reconnaissance des villes écrites dans leur nomenclature anglaise, et non plus française. - quelle localité garder à la fin ? Car il existe deux niveaux de lecture : le lieux où se passe l’action discutée dans l’article, et les autres lieux auxquels l’article fait référence comme exemple de démonstration.
Il faudra pour le coup en discuter avec le chercheur. Dans notre exercice, tous les titres sont en français, et on garde toutes les localités.
Voici le script en question :
regex=$(cut -f1 lieux | paste -s -d'|')
while read article
do
echo $article |
( grep -Eo "$regex" || printf '\n' ) |
sort -u |
paste -s -d'|'
done < Afrique.tsv |
sed '1 s/.*/lieux/' |
paste Afrique.tsv -
Détaillons le un peu.
(cette première ligne récupère la première colonne du fichier
puis elle colle chaque lieux l’un derrière l’autre séparé par un pipe
donnant ce résultat : Strasbourg|Russie|Mali|Niger|Burkina Faso|Pouet|Afrique de l’Ouest
ce résultat est contenu dans une variable $regex que l’on utilisera pour se référer à chaque lieu)
regex=$(cut -f1 lieux | paste -s -d'|')
(à chaque fois qu’on lit une ligne, qui correspond à un article)
while read article
(affiche la ligne en question et cherche si quelque part dans son contenu une ligne de caractère correspond au contenu de la regex
si ce n’est pas le cas, fais un saut de ligne
puis rassemble en une seule occurrence s’il y a plusieurs fois la même ville pour une ligne
puis ??
s’il y a plusieurs lieux différents, les coller et les séparer avec un pipe)
do
echo $article |
( grep -Eo "$regex" || printf '\n' ) |
sort -u |
paste -s -d'|'
done < Afrique.tsv |
(puis on remplace la première ligne vide par le mot ‘lieux’)
sed '1 s/.*/lieux/' |
(puis on colle le stdin dans le fichier.tsv)
paste Afrique.tsv -
A la fin on obtient un fichier.tsv avec une colonne supplémentaire mentionnant les lieux présents dans le titre et dans l’abstract.
Mais on a un problème !
Bien que cette méthode semble fonctionner pour un petit fichier.tsv de lieux, donner un trop grand nombre de lieux provoque une erreur du script :
En effet j’ai pu récupérer 12 000 lignes soit 12 000 villes en interrogeant wikidata grâce au wiki Query Service et en sélectionnant leur exemple concernant les plus grosses villes des pays du monde :
De là j’ai pu récupérer le format tsv et le transformer pour ne garder que la colonne concernant le nom des villes ainsi que leur points de géolocalisation.
Conclusions
Commandes :
tr -d 'a'
: pour supprimer un caractèretr -s
: pour squeezenl
: number lines of file dans le shellctrl+V
: faire comprends au shell que la prochaine commande est à comprendre comme une touche du clavierpaste
sort
Il est préférable de travailler avec du tsv que que csv, puisque le tsv repose sur une réparation des champs par tabulation et non pas des virgules.