Analyser des données demande de savoir manipuler aussi du texte. Ce que nous appelons texte en tant qu’humain est interprété par R comme une chaîne de caractères.
Le type de donnée correspondant dans R est appelé: character.
class("abcdR")
## [1] "character"
Il est parfois nécessaire d’extraire des motifs particuliers de chaînes de caractères. Pour ce faire on peut utiliser des expressions régulières ou regex en anglais.
Pour cela nous allons utiliser {stringr}, un package du tidyverse.
library(stringr)
Considérons un vecteur de noms de fichiers csv.
noms_fichiers <- c("pop_FRA_2019.csv", "pop_ITA_2020.csv", "pop_ESP_2019.csv")
Comment extraire le code iso3 (FRA, ITA…) ?
str_extract(string = noms_fichiers, pattern = "[A-Z]{3}")
## [1] "FRA" "ITA" "ESP"
Ici le motif (pattern) à extraire correspond à une lettre majuscule [A-Z] répétée exactement {3} fois. Facile !
Mais malheureusement la vie n’est jamais aussi simple…
noms_fichiers <- c("pop_fra_2019.csv", "pop_ita_2020.csv", "pop_esp_2019.csv")
Dans ce cas précis notre exemple précédent ne fonctionne plus car tout est en minuscule. Nous devrions utiliser la version minuscule du pattern: "[a-z]{3}", une lettre minuscule [a-z] répétée exactement {3} fois. Mais cela ne correspond plus à un motif unique.
str_extract(noms_fichiers, "[a-z]{3}")
## [1] "pop" "pop" "pop"
Il est alors nécessaire de sortir l’artillerie lourde…
str_extract(noms_fichiers, "(?<=pop_)[a-z]{3}(?=_\\d{4})")
## [1] "fra" "ita" "esp"
Ce motif, "(?<=pop_)[a-z]{3}(?=_\\d{4})" se lit,
(?<=pop_), ce qui est précédé(?<=)parpop_."[a-z]{3}", une lettre minuscule[A-Z]répétée exactement{3}.(?=_\\d{4}), ce qui est suivi(?=)par un chiffre\\drépété exactement{4}fois.
Pour être totalement rigoureux, on peut rajouter:
str_extract(noms_fichiers, "(?<=^pop_)[a-z]{3}(?=_\\d{4}\\.csv$)")
## [1] "fra" "ita" "esp"
^commence parpop_.\\.csvse termine$par l’extension “point”\\.,csv.
Il est parfois complexe d’utiliser ce genre de symboles appelés lookarounds, (?=) et (?<=). Une alternative plus simple est de tirer profit de la notion de groupe.
En regex on définit un groupe en utilisant des parenthèses.
str_replace(
string = noms_fichiers,
pattern = "^pop_([a-z]{3})_\\d{4}\\.csv$",
replacement = "\\1"
)
## [1] "fra" "ita" "esp"
Ici on définit le motif complet en rajoutant des parenthèses autour du motif à extraire: ([a-z]{3}). On demande à str_replace() de remplacer la chaîne complète par le premier groupe définit (le seul et l’unique) avec \\1.
Et voilà, les regex sont une technique difficile à appréhender pour les débutants mais ô combien utile à celles ou ceux qui la maîtrisent.
Pour en savoir plus:
