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\\d
ré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_
.\\.csv
se 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: