× Besoin d'aide pour apprendre R ? Inscrivez-vous au cours d'introduction à R d'Applied Epi, essayez nos tutoriels R gratuits, postez dans notre forum de questions et réponses de la communauté, ou demandez-nous des informations sur notre service d'assistance R.

10 Caractères et chaînes de caractères

Cette page démontre l’utilisation du paquet stringr pour évaluer et manipuler des valeurs de caractères (ou chaînes de caractères, ce que nous appelons “strings” en anglais).

  1. Combiner, ordonner, séparer, arranger - str_c(), str_glue(), str_order(), str_split()
  2. Nettoyer et standardiser
  3. Évaluer et extraire par position - str_length(), str_sub(), word().
  4. Modèles
  5. Expressions régulières (“regex”)

Afin d’expliquer facilement l’utilisation des chaînes de caractères dans le présent chapitre, la plupart des exemples utilisent un vecteur de caractères court et défini, mais ils peuvent facilement être adaptés à une colonne dans un dataframe.

Une grande partie de l’inspiration pour ce chapitre est basée sur cette example de le paquet stringr.

10.1 Preparation

Charger les paquets

Installez ou chargez le paquet stringr et d’autres paquets de tidyverse.

# installer/charger les paquets
pacman::p_load(
  stringr,    # de nombreuses fonctions pour la manipulation des chaînes de caractères
  tidyverse,  # pour diverses options de manipulation des données 
  tools)      # alternative pour la conversion en majuscules

Importation de données

Dans cette page, il y aura parfois des références à la linelist (liste de cas ou liste linéaire) nettoyée des cas d’une épidémie d’Ebola simulée. Si vous voulez suivre les exemples dans votre propre script, cliquez ici pour télécharger la “linelist” nettoyée (as .rds file). Importez les données avec la fonction import() du paquet rio (la fonction import() peut être utilisée pour importer plusieurs types de fichiers comme .xlsx, .csv, .rds - voir la page Importation et exportation pour plus de détails).

# importez la linelist de cas
linelist <- import("linelist_cleaned.rds")

Les 50 premiéres lignes de la linelist (liste linéaire ou liste de cas) sont affichées ci-dessous.

10.2 Unir, séparer et arranger

Cette section couvre :

Combiner des chaînes de caractères

Pour combiner ou concaténer plusieurs chaînes de caractères en une seule chaîne, nous suggérons d’utiliser la fonction str_c() du paquet stringr. Si vous avez des valeurs de caractères distinctes à combiner, fournissez-les simplement comme arguments uniques, séparés par des virgules.

str_c("String1", "String2", "String3")
## [1] "String1String2String3"

L’argument sep = insére une valeur de caractère entre chacun des arguments que vous avez fournis (par exemple, fournir une virgule, un espace ou une nouvelle ligne insérerait ce caractère entre chaque argument "\n")

str_c("String1", "String2", "String3", sep = ", ")
## [1] "String1, String2, String3"

L’argument collapse = est pertinent si vous mettez plusieurs vecteurs comme arguments à str_c(). L’argument collapse = est utilisé pour séparer les éléments inclus dans le vecteur produit par str_c(), où le vecteur produit est un long vecteur de type caractère.

L’exemple ci-dessous montre la combinaison de deux vecteurs en un seul vecteur (prénoms et noms de famille). Un autre exemple similaire pourrait être montré avec des régions et le nombre de cas dans chaque région. Dans cet exemple :

  • La valeur sep = apparaît entre chaque prénom et chaque nom.
  • La valeur collapse = apparaît entre chaque personne.
first_names <- c("abdul", "fahruk", "janice") 
last_names  <- c("hussein", "akinleye", "okeke")

# sep s'affiche entre les chaînes de caractères d'entrée respectives, tandis que collapse s'affiche entre les éléments produits
str_c(first_names, last_names, sep = " ", collapse = ";  ")
## [1] "abdul hussein;  fahruk akinleye;  janice okeke"

Remarque: Selon le contexte d’affichage souhaité, lorsque vous imprimez une telle chaîne combinée avec des nouvelles lignes, vous devrez peut-être envelopper la phrase entière dans cat() pour que les nouvelles lignes s’impriment correctement:

# Pour que les nouvelles lignes s'impriment correctement, il peut être nécessaire d'envelopper la phrase dans cat()
cat(str_c(first_names, last_names, sep = " ", collapse = ";\n"))
## abdul hussein;
## fahruk akinleye;
## janice okeke

Chaînes de caractères dynamiques

Utilisez la fonction str_glue() pour insérer du code R dynamique dans une chaîne de caractères. C’est une fonction trés utile pour créer des légendes de graphiques dynamiques, comme démontré ci-dessous.

  • Tout le contenu est placé entre guillemets doubles comme ceci str_glue("").
  • Tout code dynamique ou référence à des valeurs prédéfinies est placé entre des accolades {} à l’intérieur des guillemets doubles. Il peut y avoir plusieurs accolades dans la même commande de str_glue().
  • Pour afficher les guillemets de caractères ’’, utilisez des guillemets simples entre les guillemets doubles (par exemple, pour le format de date - voir l’exemple ci-dessous).
  • Conseil : Vous pouvez utiliser \n pour forcer une nouvelle ligne.
  • Conseil : Vous pouvez utiliser format() pour ajuster l’affichage de la date, et utiliser Sys.Date() pour afficher la date actuelle.

Un exemple simple, d’une légende d’un graphique dynamique :

str_glue("Les données incluent {nrow(linelist)} cas et sont actuelles à {format(Sys.Date(), '%d %b %Y')}.")
## Les données incluent 5888 cas et sont actuelles à 25 May 2023.

Un format alternatif consiste à utiliser des caractères de remplacement à l’intérieur des parenthèses et à définir le code dans des arguments séparés à la fin de la fonction str_glue(), comme ci-dessous. Cela peut améliorer la lisibilité du code si le texte est long.

str_glue("Linelist à la {current_date}.\nDernier cas hospitalisé à l'hôpital {last_hospital}.\n{n_missing_onset} cas n'ont pas de date d'apparition et ne sont pas représentés.",
         current_date = format(Sys.Date(), '%d %b %Y'),
         last_hospital = format(as.Date(max(linelist$date_hospitalisation, na.rm=T)), '%d %b %Y'),
         n_missing_onset = nrow(linelist %>% filter(is.na(date_onset)))
         )
## Linelist à la 25 May 2023.
## Dernier cas hospitalisé à l'hôpital 30 Apr 2015.
## 256 cas n'ont pas de date d'apparition et ne sont pas représentés.

Extraction d’un dataframe

Il est parfois utile d’extraire des données d’un dataframe et de les coller ensemble en séquence.Vous trouverez ci-dessous un exemple de dataframe comprenant la juridiction (zone), les nouvelles affaires et les affaires totales. Nous allons l’utiliser pour faire une description résumée du nombre de nouveaux cas et du nombre total de cas par juridiction.

# créer un dataframe de cas
case_table <- data.frame(
  zone        = c("Zone 1", "Zone 2", "Zone 3", "Zone 4", "Zone 5"),
  new_cases   = c(3, 0, 7, 0, 15),
  total_cases = c(40, 4, 25, 10, 103)
  )

Utilisez la fonction str_glue_data(), qui est spécifiquement utilisée pour prendre des données à partir des lignes du dataframe:

case_table %>% 
  str_glue_data("{zone}: {new_cases} ({total_cases} total cases)")
## Zone 1: 3 (40 total cases)
## Zone 2: 0 (4 total cases)
## Zone 3: 7 (25 total cases)
## Zone 4: 0 (10 total cases)
## Zone 5: 15 (103 total cases)

Combinaison des chaînes de caractères entre les lignes

Si vous essayez “d’enrouler” des valeurs dans une colonne d’un dataframe, c’est-à-dire de combiner des valeurs de plusieurs lignes en une seule ligne en les collant ensemble avec un séparateur. Consultez la section de la page Deduplication sur les valeurs “enroulées”.

Dataframe combiné en une seule ligne

Vous pouvez faire apparaêtre la description résumée sur une seule ligne en utilisant str_c() (en spécifiant le dataframe et les noms des colonnes), et en fournissant les arguments sep = et collapse =.

str_c(case_table$zone, case_table$new_cases, sep = " = ", collapse = ";  ")
## [1] "Zone 1 = 3;  Zone 2 = 0;  Zone 3 = 7;  Zone 4 = 0;  Zone 5 = 15"

Vous pouvez ajouter le pré-fixe “New Cases :” (nouveaux cas en français) au début de la description en l’entourant d’une str_c() distincte (si “New Cases :” se trouvait dans la `str_c()``, il apparaîtrait plusieurs fois).

str_c("New Cases: ", str_c(case_table$zone, case_table$new_cases, sep = " = ", collapse = ";  "))
## [1] "New Cases: Zone 1 = 3;  Zone 2 = 0;  Zone 3 = 7;  Zone 4 = 0;  Zone 5 = 15"

Unir les colonnes

Dans un cadre de données, le regroupement des valeurs de caractères de plusieurs colonnes peut être réalisé avec la fonction unite() du paquet tidyr. C’est l’inverse de la fonction separate().

Vous devez fournir le nom de la nouvelle colonne unie et ensuite fournir les noms des colonnes que vous souhaitez unir.

  • Par défaut, le séparateur utilisé dans la colonne unie est le caractère de soulignement _, mais cela peut être changé avec l’argument sep =.
  • L’argument remove = supprime les colonnes qui seront unies du dataframe (VRAI par défaut).
  • L’argument na.rm = supprime les valeurs manquantes lors de l’unification (FAUX par défaut)

Ci-dessous, nous définissons un mini dataframe pour la démonstration:

df <- data.frame(
  case_ID = c(1:6),
  symptoms  = c("jaundice, fever, chills",     # patient 1
                "chills, aches, pains",        # patient 2 
                "fever",                       # patient 3
                "vomiting, diarrhoea",         # patient 4
                "bleeding from gums, fever",   # patient 5
                "rapid pulse, headache"),      # patient 6
  outcome = c("Recover", "Death", "Death", "Recover", "Recover", "Recover"))
df_split <- separate(df, symptoms, into = c("sym_1", "sym_2", "sym_3"), extra = "merge")
## Warning: Expected 3 pieces. Missing pieces filled with `NA` in 2 rows [3, 4].

Voici l’exemple avec le dataframe dessus:

Ci-dessous, nous réunissons les trois colonnes de symptômes:

df_split %>% 
  unite(
    col = "all_symptoms", # nom de la nouvelle colonne unie
    c("sym_1", "sym_2", "sym_3"), # colonnes à unir
    sep = ", ", # séparateur à utiliser dans la colonne unie
    remove = TRUE, # si TRUE (VRAI), supprime les colonnes d'entrée du dataframe
    na.rm = TRUE # Si TRUE (VRAI), les valeurs manquantes sont supprimées avant l'unification.
  )
##   case_ID                all_symptoms outcome
## 1       1     jaundice, fever, chills Recover
## 2       2        chills, aches, pains   Death
## 3       3                       fever   Death
## 4       4         vomiting, diarrhoea Recover
## 5       5 bleeding, from, gums, fever Recover
## 6       6      rapid, pulse, headache Recover

séparer

Pour diviser une chaîne de caractères en fonction d’un motif, utilisez la fonction str_split(). Cette fonction évalue la (ou les) chaîne(s) de caractères et renvoie une liste de vecteurs de caractères constituée des valeurs nouvellement séparées.

L’exemple simple ci-dessous évalue une chaîne de caractères et la divise en trois. Par défaut, il retourne un objet de la classe list avec un élément (un vecteur de caractères) pour chaque chaîne initialement fournie. Si simplify = TRUE, (en français VRAI), il retourne une matrice de caractères.

Dans cet exemple, une chaîne de caractères est fournie, et la fonction renvoie une liste avec un élément - un vecteur de caractères avec trois valeurs.

str_split(string = "jaundice, fever, chills",
          pattern = ",")
## [[1]]
## [1] "jaundice" " fever"   " chills"

Si les valeurs séparées sont enregistrées dans un objet, vous pouvez alors accéder à la n-iéme valeur séparée avec la syntaxe des crochets. Pour accéder à une valeur spécifique, vous pouvez utiliser une syntaxe comme celle-ci : nouveau_objet[[1]][2], qui accéderait à la deuxiéme valeur de la premiére chaîne évaluée (“fever”, ou fiévre en français, dans le dataframe de l’exemple). Consultez la page Bases de R pour plus de détails sur l’accés aux éléments.

pt1_symptoms <- str_split("jaundice, fever, chills", ",")

pt1_symptoms[[1]][2]  # extrait la 2éme valeur du 1er (et dans ce cas unique) élément de la liste
## [1] " fever"

Si plusieurs chaînes de caractères sont fournies par str_split(), il y aura plus d’un élément dans la liste retournée.

symptoms <- c("jaundice, fever, chills",     # patient 1
              "chills, aches, pains",        # patient 2 
              "fever",                       # patient 3
              "vomiting, diarrhoea",         # patient 4
              "bleeding from gums, fever",   # patient 5
              "rapid pulse, headache")       # patient 6

str_split(symptoms, ",")                     # split each patient's symptoms
## [[1]]
## [1] "jaundice" " fever"   " chills" 
## 
## [[2]]
## [1] "chills" " aches" " pains"
## 
## [[3]]
## [1] "fever"
## 
## [[4]]
## [1] "vomiting"   " diarrhoea"
## 
## [[5]]
## [1] "bleeding from gums" " fever"            
## 
## [[6]]
## [1] "rapid pulse" " headache"

Pour retourner une “matrice de caractères” à la place, ce qui peut être utile pour créer des colonnes dans votre dataframe, définissez l’argument simplify = TRUE comme indiqué ci-dessous :

str_split(symptoms, ",", simplify = TRUE) #simplify = VRAI
##      [,1]                 [,2]         [,3]     
## [1,] "jaundice"           " fever"     " chills"
## [2,] "chills"             " aches"     " pains" 
## [3,] "fever"              ""           ""       
## [4,] "vomiting"           " diarrhoea" ""       
## [5,] "bleeding from gums" " fever"     ""       
## [6,] "rapid pulse"        " headache"  ""

Vous pouvez également ajuster le nombre de séparations à créer avec l’argument n =. Par exemple, l’exemple ci-dessous limite le nombre de séparations à deux. Toutes les autres virgules restent dans les deuxiémes valeurs.

str_split(symptoms, ",", simplify = TRUE, n = 2)
##      [,1]                 [,2]            
## [1,] "jaundice"           " fever, chills"
## [2,] "chills"             " aches, pains" 
## [3,] "fever"              ""              
## [4,] "vomiting"           " diarrhoea"    
## [5,] "bleeding from gums" " fever"        
## [6,] "rapid pulse"        " headache"

Note - les mêmes résultats peuvent être obtenus avec str_split_fixed(), dans lequel vous ne donnez pas l’argument simplify, mais devez à la place désigner le nombre de colonnes (n).

str_split_fixed(symptoms, ",", n = 2)

Séparer les colonnes

Si vous essayez de séparer une colonne dans un dataframe, il est préférable d’utiliser la fonction separate() de dplyr. Cette fonction est utilisée pour séparer une colonne de caractères en d’autres colonnes.

Disons que nous avons un simple dataframe df (défini et uni dans la section unite) contenant une colonne case_ID, une colonne de caractères avec plusieurs symptômes, et une colonne de résultats. Notre objectif est de séparer la colonne symptoms en plusieurs colonnes, chacune contenant un symptôme.

En supposant que les données sont passées (‘pipe’, en utilisant %>%) dans separate(), vous devez d’abord fournir la colonne à séparer dans la fonction seperate(). Ensuite, fournissez into = comme un vecteur c( ) contenant les noms des nouvelles colonnes, comme indiqué ci-dessous.

  • sep = le séparateur, peut être un caractère, ou un nombre (interprété comme la position du caractère à séparer)
  • remove = FAUX par défaut, supprime la colonne sélectionnée du dataframe une fois séparée.
  • convert = FALSE par défaut, si TRUE, les “NA” de la chaîne deviendront des NA.
  • extra = ce contréle ce qui se passe s’il y a plus de valeurs créées par la séparation de la colonne que de nouveaux noms de colonnes fournis.
    • extra = "warn" signifie que vous verrez un avertissement mais que les valeurs excédentaires seront supprimées (par défaut).
    • extra = "drop", signifie que les valeurs excédentaires seront abandonnées sans avertissement.
      **extra = "merge" ne fractionnera que le nombre de nouvelles colonnes listées dans into - *cette configuration préservera toutes vos données**.

Voici un exemple avec extra = "merge" - Deux nouvelles colonnes sont définies mais tous les troisiémes symptômes ou plus sont combinés dans la deuxiéme colonne:

# troisiémes symptômes combinés dans la deuxiéme nouvelle colonne
df %>% 
  separate(symptoms, into = c("sym_1", "sym_2"), sep=",", extra = "merge")
## Warning: Expected 2 pieces. Missing pieces filled with `NA` in 1 rows [3].
##   case_ID              sym_1          sym_2 outcome
## 1       1           jaundice  fever, chills Recover
## 2       2             chills   aches, pains   Death
## 3       3              fever           <NA>   Death
## 4       4           vomiting      diarrhoea Recover
## 5       5 bleeding from gums          fever Recover
## 6       6        rapid pulse       headache Recover

Lorsque l’option par défaut est utilisée ci-dessous, R retourne un avertissement mais les troisiémes symptômes sont perdus:

# les troisiémes symptômes sont perdus
df %>% 
  separate(symptoms, into = c("sym_1", "sym_2"), sep=",")
## Warning: Expected 2 pieces. Additional pieces discarded in 2 rows [1, 2].
## Warning: Expected 2 pieces. Missing pieces filled with `NA` in 1 rows [3].
##   case_ID              sym_1      sym_2 outcome
## 1       1           jaundice      fever Recover
## 2       2             chills      aches   Death
## 3       3              fever       <NA>   Death
## 4       4           vomiting  diarrhoea Recover
## 5       5 bleeding from gums      fever Recover
## 6       6        rapid pulse   headache Recover

CAUTION: Si vous ne fournissez pas suffisamment de valeurs into pour les nouvelles colonnes, vos données peuvent être tronquées.

Classer par ordre alphabétique

Vous pouvez trier plusieurs chaînes de caractères par ordre alphabétique. str_order() renvoie l’ordre (numérique), tandis que str_sort() renvoie les chaînes de caractères dans l’ordre alphabétique.

# chaînes de caractères
health_zones <- c("Alba", "Takota", "Delta")

# renvoie l'ordre alphabétique
str_order(health_zones)
## [1] 1 3 2
# retourne les chaînes de caractères par ordre alphabétique
str_sort(health_zones)
## [1] "Alba"   "Delta"  "Takota"

Pour utiliser un alphabet différent, ajoutez l’argument locale =. Voir la liste complète des locales en entrant stringi::stri_locale_list() dans la console R.

Fonctions de la base R

Il est courant de voir les fonctions base R paste() et paste0(), qui concaténent des vecteurs aprés avoir converti toutes les parties en caractères. Ces fonctions agissent de manière similaire à str_c() mais la syntaxe est sans doute plus compliquée - dans les parenthèses, chaque partie est séparée par une virgule. Les parties sont soit du texte en caractères (entre guillemets), soit des objets de code prédéfinis (sans guillemets). Par exemple:

n_beds <- 10
n_masks <- 20

paste0("Regional hospital needs ", n_beds, " beds and ", n_masks, " masks.")
## [1] "Regional hospital needs 10 beds and 20 masks."

Les arguments sep = et collapse = peuvent être spécifiés. paste() est simplement paste0() avec un sep = " " (un espace) par défaut.

10.3 Nettoyer et standardiser

Changer la casse

Souvent, on doit modifier la casse/capitalisation d’une valeur de chaîne de caractères, par exemple les noms des jursidictions. Utilisez str_to_upper(), str_to_lower(), et str_to_title(), de stringr, comme indiqué ci-dessous :

str_to_upper("California")
## [1] "CALIFORNIA"
str_to_lower("California")
## [1] "california"

En utilisant *base** R, l’exemple ci-dessus peut également être réalisé avec toupper() ou tolower().

Mots en majuscules

La transformation de la chaîne pour que chaque mot soit en majuscule peut être réalisée avec str_to_title():

str_to_title("go to the US state of california ")
## [1] "Go To The Us State Of California "

Utilisez la fonction toTitleCase() du paquet tools pour ne mettre en majuscules que certains mots (les mots comme “to”, “the” et “of” ne sont pas mis en majuscules).

tools::toTitleCase("This is the US state of california")
## [1] "This is the US State of California"

Vous pouvez également utiliser la fonction str_to_sentence(), qui ne met en majuscule que la premiére lettre de la chaîne.

str_to_sentence("the patient must be transported")
## [1] "The patient must be transported"

Longueur du bloc

Utilisez la fonction str_pad() pour ajouter des caractères à une chaîne, jusqu’à une longueur minimale. Par défaut, des espaces sont ajoutés, mais vous pouvez également ajouter d’autres caractères en utilisant l’argument pad =.

# Codes ICD de longueur différente
ICD_codes <- c("R10.13",
               "R10.819",
               "R17")

# Les codes ICD sont complétés à 7 caractères sur la droite
str_pad(ICD_codes, 7, "right")
## [1] "R10.13 " "R10.819" "R17    "
# Remplir avec des points au lieu d'espaces
str_pad(ICD_codes, 7, "right", pad = ".")
## [1] "R10.13." "R10.819" "R17...."

Par exemple, pour complèter des nombres avec des zéros en tête (comme pour les heures ou les minutes), vous pouvez complèter le nombre à une longueur minimale de 2 avec pad = "0".

# Ajoutez des zéros à deux chiffres (par exemple, pour les minutes/heures)
str_pad("4", 2, pad = "0") 
## [1] "04"
# Exemple utilisant une colonne numérique nommée "heures" (hours en Anglais)
# hours <- str_pad(hours, 2, pad = "0")

Tronquer

La fonction str_trunc() définit une longueur maximale pour chaque chaîne. Si une chaîne dépasse cette longueur, elle est tronquée (raccourcie) et une ellipse (…) est incluse pour indiquer que la chaîne était auparavant plus longue. Notez que l’ellipse est comptée dans la longueur. Les caractères d’ellipses peuvent être changés avec l’argument ellipsis =. L’argument optionnel side = spécifie où l’ellipse apparaîtra dans la chaîne tronquée (“gauche”, “droite”, ou “centre”).

original <- "Symptom onset on 4/3/2020 with vomiting"
str_trunc(original, 10, "center")
## [1] "Symp...ing"

Normaliser la longueur

Utilisez la fonction str_trunc() pour définir une longueur maximale, puis utilisez str_pad() pour étendre les chaînes trés courtes à cette longueur tronquée. Dans l’exemple ci-dessous, 6 est défini comme longueur maximale (une valeur est tronquée), puis une valeur trés courte est ajoutée pour atteindre la longueur de 6.

# Codes CIM de longueur différente
ICD_codes   <- c("R10.13",
                 "R10.819",
                 "R17")

# tronquer à la longueur maximale de 6
ICD_codes_2 <- str_trunc(ICD_codes, 6)
ICD_codes_2
## [1] "R10.13" "R10..." "R17"
# étendre à une longueur minimale de 6
ICD_codes_3 <- str_pad(ICD_codes_2, 6, "right")
ICD_codes_3
## [1] "R10.13" "R10..." "R17   "

Supprimer les espaces avant/aprés les chaînes de caractères

Utilisez la fonction str_trim() pour supprimer les espaces, les nouvelles lignes (\n) ou les tabulations (\t) sur les côtés d’une entrée de chaîne de caractères. Ajoutez "right" (en français droite), "left" (en français gauche) ou "both" (en français les deux) à la commande pour spécifier le côté à découper (par exemple, str_trim(x, "right").

# Numéros d'identification avec espaces excédentaires à droite
IDs <- c("provA_1852  ", # deux espaces excédentaires
         "provA_2345",   # zero espace excédentaire
         "provA_9460 ")  # un espace excédentaire

#  les identifiants sont coupés pour supprimer les espaces excédentaires du côté droit uniquement
str_trim(IDs)
## [1] "provA_1852" "provA_2345" "provA_9460"

Supprimer les espaces répétés dans les chaînes de caractères

Utilisez la fonction str_squish() pour supprimer les espaces répétés qui apparaissent à l’intérieur d’une chaîne. Par exemple, pour convertir les espaces doubles en espaces simples. Elle supprime également les espaces, les retours à la ligne ou les tabulations à l’extérieur de la chaîne, comme str_trim().

# L'original contient des espaces supplémentaires dans la chaîne
str_squish("  Pt requires   IV saline\n") 
## [1] "Pt requires IV saline"

Entrez ?str_trim, ?str_pad dans votre console R pour voir plus de détails.

Transformer en paragraphes

Utilisez str_wrap() pour transformer un long texte non structuré en un paragraphe structuré avec une longueur de ligne fixe. Fournissez la longueur idéale de caractères pour chaque ligne, et la fonction applique un algorithme pour insérer des nouvelles lignes (\n) dans le paragraphe, comme dans l’exemple ci-dessous.

pt_course <- "Début des symptômes 1/4/2020 : vomissements, frissons, fièvre. Le patient a vu un guérisseur traditionnel dans son village natal le 2/4/2020. Le 5/4/2020, les symptômes du patient se sont aggravés et il a été admis à la clinique Lumta. Un échantillon a été prélevé et le patient a été transporté à l'hôpital régional le 6/4/2020. Le patient est décédé à l'hôpital régional le 7/4/2020."

str_wrap(pt_course, 40)
## [1] "Début des symptômes 1/4/2020 :\nvomissements, frissons, fièvre. Le\npatient a vu un guérisseur traditionnel\ndans son village natal le 2/4/2020. Le\n5/4/2020, les symptômes du patient se\nsont aggravés et il a été admis à la\nclinique Lumta. Un échantillon a été\nprélevé et le patient a été transporté\nà l'hôpital régional le 6/4/2020. Le\npatient est décédé à l'hôpital régional\nle 7/4/2020."

La fonction de base R cat()` peut être enroulée autour de la commande ci-dessus afin d’imprimer le résultat dans la console R.

cat(str_wrap(pt_course, 40))
## Début des symptômes 1/4/2020 :
## vomissements, frissons, fièvre. Le
## patient a vu un guérisseur traditionnel
## dans son village natal le 2/4/2020. Le
## 5/4/2020, les symptômes du patient se
## sont aggravés et il a été admis à la
## clinique Lumta. Un échantillon a été
## prélevé et le patient a été transporté
## à l'hôpital régional le 6/4/2020. Le
## patient est décédé à l'hôpital régional
## le 7/4/2020.

10.4 Gérer par position

Extraire par position de caractère

Utilisez la fonction str_sub() pour retourner seulement une partie d’une chaîne de caractères. La fonction prend trois arguments principaux :

  1. le(s) vecteur(s) de caractères
  2. la position de départ dans le vecteur
  3. la position finale dans le vecteur

Quelques remarques sur les numéros de position :

  • Si le numéro de position est positif, la position est comptée à partir de l’extrémité gauche de la chaîne.
  • Si le numéro de position est négatif, il est compté à partir de l’extrémité droite de la chaîne.
  • Les numéros de position sont inclusifs.
  • Les positions qui dépassent la chaîne de caractères seront tronquées (supprimées).

Voici quelques exemples appliqués à la chaîne “pneumonie” :

# position de départ et position finale troisiéme en partant de la gauche (3éme lettre en partant de la gauche)
str_sub("pneumonia", 3, 3)
## [1] "e"
# 0 n'est pas présent, donc cela renvoie ""
str_sub("pneumonia", 0, 0)
## [1] ""
# # 6éme en partant de la gauche, jusqu'à  la 1ére en partant de la droite
str_sub("pneumonia", 6, -1)
## [1] "onia"
# 5éme de la droite, vers le 2éme de la droite
str_sub("pneumonia", -5, -2)
## [1] "moni"
# 4éme en partant de la gauche, jusqu'à  une position en dehors de la chaîne de caractères
str_sub("pneumonia", 4, 15)
## [1] "umonia"

Extraire par position de mot

Pour extraire le niéme “mot”, utilisez la fonction word(), du paquet stringr. Fournissez la ou les chaînes de caractères, puis la premiére position du mot à extraire, et la dernière position du mot à extraire.

Par défaut, le séparateur entre les mots est supposé être un espace, sauf indication contraire avec sep = (par exemple, sep = "_" où les mots sont séparés par des caractères de soulignement).

# chaînes de caractères à évaluer
chief_complaints <- c("I just got out of the hospital 2 days ago, but still can barely breathe.",
                      "My stomach hurts",
                      "Severe ear pain")

# extract 1st to 3rd words of each string
word(chief_complaints, start = 1, end = 3, sep = " ")
## [1] "I just got"       "My stomach hurts" "Severe ear pain"

Remplacer par la position du caractère

str_sub() apparié avec l’opérateur d’affectation (<-) peut être utilisé pour modifier une partie d’une chaîne :

word <- "pneumonia"

# convertissez les troisiéme et quatriéme caractères en X 
str_sub(word, 3, 4) <- "XX"

# imprimer
word
## [1] "pnXXmonia"

Voici ci-dessus Un exemple appliqué à plusieurs chaînes de caractères (par exemple, un vecteur de mots ou une colonne). Notez l’expansion en longueur de “HIV”.

words <- c("pneumonia", "tubercolosis", "HIV")

# convertissez les troisiéme et quatriéme caractères en X 
str_sub(words, 3, 4) <- "XX"

words
## [1] "pnXXmonia"    "tuXXrcolosis" "HIXX"

Evaluer la longueur

str_length("abc")
## [1] 3

Alternativement, utilisez la fonction nchar() de base R.

10.5 Motifs

De nombreuses fonctions du paquet stringr fonctionnent pour détecter, localiser, extraire, correspondre, remplacer et séparer en fonction d’un motif spécifié.

détecter un motif

Utilisez la fonction str_detect() comme ci-dessous pour détecter la présence/absence d’un motif dans une chaîne de caractères. Fournissez d’abord la chaîne ou le vecteur à rechercher (string =), puis le motif à rechercher (pattern =). Notez que par défaut, la recherche est sensible à la casse!

str_detect(string = "primary school teacher", pattern = "teach")
## [1] TRUE

L’argument negate = peut être inclus et mis à TRUE (en français VRAI) si vous voulez savoir si le motif n’est PAS présent.

str_detect(string = "primary school teacher", pattern = "teach", negate = TRUE)
## [1] FALSE

Pour ignorer les majuscules et les minuscules, intégrez le motif dans regex(), et dans regex() ajoutez l’argument ignore_case = TRUE (ou T en raccourci).

str_detect(string = "Teacher", pattern = regex("teach", ignore_case = T))
## [1] TRUE

Lorsque str_detect() est appliqué à un vecteur de caractères ou à une colonne de dataframe, il renvoie TRUE (en français VRAI) ou FALSE (en français FAUX) pour chacune des valeurs.

# un vecteur/colonne de professions 
occupations <- c("field laborer",
                 "university professor",
                 "primary school teacher & tutor",
                 "tutor",
                 "nurse at regional hospital",
                 "lineworker at Amberdeen Fish Factory",
                 "physican",
                 "cardiologist",
                 "office worker",
                 "food service")

# détecter la présence du motif "teach" dans chaque chaîne - la valeur retournée est un vecteur de VRAI/FAUX
str_detect(occupations, "teach")
##  [1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

Si vous avez besoin de compter les TRUEs, utilisez la fonction sum() sur les valeurs ou le vecteur retourné(es). Ceci compte le nombre de TRUE (VRAI) dans les valeurs ou le vecteur retourné(es).

sum(str_detect(occupations, "teach"))
## [1] 1

Pour effectuer une recherche incluant plusieurs termes, incluez-les séparés par des barres OR (|) dans l’argument pattern =, comme indiqué ci-dessous:

sum(str_detect(string = occupations, pattern = "teach|professor|tutor"))
## [1] 3

Si vous avez besoin de construire une longue liste de termes de recherche, vous pouvez les combiner en utilisant str_c() et sep = |, et assigner ceci à un objet. Vous pouvez ensuite référencer le vecteur par le nom de l’objet. L’exemple ci-dessous combine les termes de recherche d’une occupation possible en un seul objet.

# termes de recherche
occupation_med_frontline <- str_c("medical", "medicine", "hcw", "healthcare", "home care", "home health",
                                "surgeon", "doctor", "doc", "physician", "surgery", "peds", "pediatrician",
                               "intensivist", "cardiologist", "coroner", "nurse", "nursing", "rn", "lpn",
                               "cna", "pa", "physician assistant", "mental health",
                               "emergency department technician", "resp therapist", "respiratory",
                                "phlebotomist", "pharmacy", "pharmacist", "hospital", "snf", "rehabilitation",
                               "rehab", "activity", "elderly", "subacute", "sub acute",
                                "clinic", "post acute", "therapist", "extended care",
                                "dental", "dential", "dentist", sep = "|")

occupation_med_frontline
## [1] "medical|medicine|hcw|healthcare|home care|home health|surgeon|doctor|doc|physician|surgery|peds|pediatrician|intensivist|cardiologist|coroner|nurse|nursing|rn|lpn|cna|pa|physician assistant|mental health|emergency department technician|resp therapist|respiratory|phlebotomist|pharmacy|pharmacist|hospital|snf|rehabilitation|rehab|activity|elderly|subacute|sub acute|clinic|post acute|therapist|extended care|dental|dential|dentist"

Cette commande renvoie le nombre de professions qui contiennent l’un des termes de recherche pour les praticiens médicaux (occupation_med_frontline):

sum(str_detect(string = occupations, pattern = occupation_med_frontline))
## [1] 2

Fonctions de recherche de chaînes de caractères de base R

La fonction de R base grepl() fonctionne de manière similaire à str_detect(), dans le sens qu’elle recherche les correspondances avec un motif et retourne un vecteur logique. La syntaxe de base est grepl(pattern, strings_to_search, ignore.case = FALSE, ...). Un avantage est que l’argument ignore.case est plus facile à écrire (il n’y a pas besoin d’impliquer la fonction regex()).

Les fonctions sub() et gsub() de base R agissent de manière similaire à str_replace(). Leur syntaxe générale suit ce format : gsub(motif, remplacement, chaînes_a_rechercher, ignore.case = FALSE). sub() remplacera seulement la premiére instance du motif, alors que gsub() remplacera toutes les instances du motif.

Convertir les virgules en points

Voici un exemple d’utilisation de gsub() pour convertir des virgules en points dans un vecteur de nombres. Cela peut être utile si vos données proviennent de différents endroits dans le monde avec une syntaxe de langue différente.

L’exemple ci-dessous utilise deux applications de gsub. L’application interne gsub(), qui agit en premier sur l’objet lengths, convertit tous les points en “” sans espace. Le caractère point “.” doit être “spécifié” avec deux slashs pour signifier réellement un point, parce que “.” en regex sans deux slashs signifie ” n’importe quel caractère”. Ensuite, le résultat (avec seulement des virgules) est passé à la fonction externe gsub() dans laquelle les virgules sont remplacées par des points.

lengths <- c("2.454,56", "1,2", "6.096,5")

as.numeric(gsub(pattern = ",",                # trouver les virgules    
                replacement = ".",            # remplacer par des points
                x = gsub("\\.", "", lengths)  # vecteur avec d'autres points supprimés 
                )
           )                                  # convertir le résultat en numérique

Remplacer tous les éléments

Utilisez la fonction str_replace_all() comme un outil de “recherche et remplacement”. Vous fournissez d’abord les chaînes à évaluer à string =, puis le motif à remplacer à pattern =, et enfin la valeur de remplacement à replacement =. L’exemple ci-dessous remplace toutes les occurrences de “dead” (en français mort) par “deceased” (en français décédés). Notez que cette opération est sensible à la casse.

outcome <- c("Karl: dead",
            "Samantha: dead",
            "Marco: not dead")

str_replace_all(string = outcome, pattern = "dead", replacement = "deceased")
## [1] "Karl: deceased"      "Samantha: deceased"  "Marco: not deceased"

Remarques :

  • Pour remplacer un motif par NA, utilisez str_replace_na().
  • La fonction str_replace() remplace uniquement la premiére instance du motif dans chaque chaîne évaluée.

détecter en utilisant des instructions logiques

A l’intérieur de case_when()

str_detect() est souvent utilisé dans case_when() (du paquet dplyr). Disons que occupations est une colonne de la linelist (liste linéaire ou liste de cas). La fonction mutate() ci-dessous crée une nouvelle colonne appelée is_educator en utilisant la logique conditionnelle via case_when(). Consultez la page sur le nettoyage des données pour en savoir plus sur la méthode case_when().

df <- df %>% 
  mutate(is_educator = case_when(
    #  recherche de termes dans la profession, non sensible à la casse
    str_detect(occupations,
               regex("teach|prof|tutor|university",
                     ignore_case = TRUE))              ~ "Educator",
    # all others
    TRUE                                               ~ "Not an educator"))

Par ailleurs, il peut être important d’ajouter des critéres d’exclusion à la logique conditionnelle (negate = F) :

df <- df %>% 
  # la valeur de la nouvelle colonne is_educator est basée sur la logique conditionnelle
  mutate(is_educator = case_when(
    
    # la colonne occupation doit répondre à 2 critéres pour se voir attribuer "Educateur" :
    # elle doit avoir un terme de recherche ET PAS de terme d'exclusion
    
    #  Doit avoir un terme de recherche
    str_detect(occupations,
               regex("teach|prof|tutor|university", ignore_case = T)) &              
    
    # AND ne doit PAS avoir de terme d'exclusion
    str_detect(occupations,
               regex("admin", ignore_case = T),
               negate = TRUE                        ~ "Educator"
    
    # Toutes les lignes ne répondant pas aux critéres ci-dessus
    TRUE                                            ~ "Not an educator"))

Localiser la position du motif

Pour localiser la premiére position d’un motif, utilisez la fonction str_locate(). Elle produit une position de début et de fin.

str_locate("I wish", "sh")
##      start end
## [1,]     5   6

Comme les autres fonctions de la famille str, il existe une version “_all” (str_locate_all()) qui renvoie les positions de toutes les instances du motif dans chaque chaîne. Cette fonction renvoie les valeurs sous forme de liste.

phrases <- c("I wish", "I hope", "he hopes", "He hopes")

str_locate(phrases, "h" ) # position de la *premiére* instance du motif
##      start end
## [1,]     6   6
## [2,]     3   3
## [3,]     1   1
## [4,]     4   4
str_locate_all(phrases, "h" ) # position de *chaque* instance du motif
## [[1]]
##      start end
## [1,]     6   6
## 
## [[2]]
##      start end
## [1,]     3   3
## 
## [[3]]
##      start end
## [1,]     1   1
## [2,]     4   4
## 
## [[4]]
##      start end
## [1,]     4   4

Extraire une correspondance

str_extract_all() retourne les motifs de correspondance eux-mêmes, ce qui est trés utile lorsque vous avez proposé plusieurs motifs via des conditions “OR” (en français OU). Par exemple, si vous cherchez dans le vecteur de chaînes de professions (voir l’exemple précédent) soit “teach”, “prof”, ou “tutor”.

str_extract_all() renvoie une liste qui contient toutes les correspondances pour chaque chaîne évaluée. Voyez ci-dessous comment l’occupation 3 contient deux correspondances de motifs.

str_extract_all(occupations, "teach|prof|tutor")
## [[1]]
## character(0)
## 
## [[2]]
## [1] "prof"
## 
## [[3]]
## [1] "teach" "tutor"
## 
## [[4]]
## [1] "tutor"
## 
## [[5]]
## character(0)
## 
## [[6]]
## character(0)
## 
## [[7]]
## character(0)
## 
## [[8]]
## character(0)
## 
## [[9]]
## character(0)
## 
## [[10]]
## character(0)

str_extract() extrait seulement la premiére correspondance dans chaque chaîne évaluée, produisant un vecteur de caractères avec un élément pour chaque chaîne évaluée. Elle retourne NA lorsqu’il n’y a pas de correspondance. Les NAs peuvent être supprimés en enveloppant le vecteur retourné avec na.exclude(). Notez que la deuxiéme correspondance de l’occupation 3 n’est pas affichée.

str_extract(occupations, "teach|prof|tutor")
##  [1] NA      "prof"  "teach" "tutor" NA      NA      NA      NA      NA      NA

Sous-ensemble et comptage

Les fonctions alignées comprennent str_subset() et str_count().

str_subset() renvoie les valeurs réelles qui contiennent le motif :

str_subset(occupations, "teach|prof|tutor")
## [1] "university professor"           "primary school teacher & tutor"
## [3] "tutor"

str_count() renvoie un vecteur de nombres : le nombre de fois qu’un terme de recherche apparaît dans chaque valeur évaluée.

str_count(occupations, regex("teach|prof|tutor", ignore_case = TRUE))
##  [1] 0 1 2 1 0 0 0 0 0 0

Groupes de regex

EN CONSTRUCTION

10.6 caractères spéciaux

Slash arriére \ comme échappement

La barre oblique inverse \ est utilisée pour “échapper” à la signification du caractère suivant. Ainsi, une barre oblique inversée peut être utilisée pour afficher un guillemet dans d’autres guillemets (\") - le guillemet central ne “cassera” pas les guillemets environnants.

Note - Si vous voulez afficher une barre oblique inverse, vous devez échapper à sa signification avec une autre barre oblique inverse. Ainsi, vous devez écrire deux barres obliques inversées \\ pour en afficher une.

Caractères spéciaux

Caractère spécial Représentation
"\\" barre oblique inversée
"\n" une nouvelle ligne (newline)
"\"" guillemets doubles entre guillemets doubles
'\'' guillemets simples entre guillemets simples
"\`" accent grave
"\r" retour chariot
"\t" tabulation
"\v" tabulation verticale
"\b" retour arriére

Exécutez ?"'" dans la console R pour afficher la liste complète de ces caractères spéciaux (elle apparaîtra dans le volet d’aide de RStudio).

10.7 Expressions régulières (regex)

10.8 Regex et caractères spéciaux

Les expressions régulières, ou “regex”, sont un langage concis pour décrire des motifs dans des chaînes de caractères. Si vous n’étes pas familier avec ce langage, une expression régulière peut ressembler à une langue étrangére. Nous allons essayer de démystifier un peu ce langage.

Une grande partie de cette section est adaptée de ce tutoriel et de cette cheatsheet. Nous adaptons ici de manière sélective, sachant que ce manuel pourrait être consulté par des personnes n’ayant pas d’accés à l’Internet pour consulter les autres tutoriels.

Une expression régulière est souvent utilisée pour extraire des motifs spécifiques d’un texte “non structuré”, par exemple des notes médicales, des plaintes principales, des antécédents du patient ou d’autres colonnes de texte libre dans un dataframe.

Il existe quatre outils de base que l’on peut utiliser pour créer une expression régulière de base :

  1. Jeux de caractères
  2. Méta-caractères
  3. Quantificateurs
  4. Groupes

Jeux de caractères

Les jeux de caractères sont une façon d’exprimer les options de liste pour une correspondance de caractères, entre parenthèses. Ainsi, une correspondance sera déclenchée si l’un des caractères entre parenthèses est trouvé dans la chaîne. Par exemple, pour rechercher des voyelles, on peut utiliser ce jeu de caractères: “[aeiou]”. Voici d’autres jeux de caractères courants:

Jeu de caractères Correspond à
"[A-Z]" toute lettre majuscule unique
"[a-z]" toute lettre minuscule unique
"[0-9]" n’importe quel chiffre
[:alnum:] tout caractère alphanumérique
[:digit:] tout chiffre numérique
[:alpha:] toute lettre (majuscule ou minuscule)
[:upper:] toute lettre majuscule
[:lower:] toute lettre minuscule

Les jeux de caractères peuvent être combinés à l’intérieur d’une même parenthèse (sans espace !), par exemple "[A-Za-z]" (toute lettre majuscule OU minuscule), ou un autre exemple "[t-z0-5]" (minuscules de t à z OU nombre de 0 à 5).

Meta characters

Les métacaractères sont des raccourcis pour les jeux de caractères. Certains des plus importants sont énumérés ci-dessous :

caractère méta Représentation
"\\s" un seul espace
"\\w" un seul caractère alphanumérique (A-Z, a-z, ou 0-9)
"\\d" un seul chiffre (0-9)

Quantificateurs

En général, vous ne souhaitez pas rechercher une correspondance sur un seul caractère. Les quantificateurs vous permettent de désigner la longueur des lettres/chiffres pour permettre une correspondance plus spécifique.

Les quantificateurs sont des nombres écrits entre accolades { } aprés le caractère qu’ils quantifient, par exemple:

  • "A{2}" renverra les instances de deux lettres majuscules A.
  • "A{2,4}" renverra les instances de deux à quatre lettres majuscules A (ne mettez pas d’espace !).
  • "A{2,}" renverra les instances de deux lettres A majuscules ou plus.
  • "A+" renverra les instances de une ou plusieurs lettres majuscules A (groupe étendu jusqu’à ce qu’un caractère différent soit rencontré).
  • Faites précéder d’un astérisque * pour obtenir zéro ou plus de correspondances (utile si vous n’étes pas sûr que le motif soit présent).

En utilisant le symbole plus + comme quantificateur, la correspondance se fera jusqu’à ce qu’un caractère différent soit rencontré. Par exemple, cette expression retournera tous les mots (caractères alpha : "[A-Za-z]+").

# chaîne de caractères pour tester les quantificateurs
test <- "A-AA-AAA-AAAA"

Lorsqu’un quantificateur de {2} est utilisé, seules les paires de A consécutifs sont renvoyées. Deux paires sont identifiées dans AAAA.

str_extract_all(test, "A{2}")
## [[1]]
## [1] "AA" "AA" "AA" "AA"

Lorsqu’un quantificateur de {2,4} est utilisé, les groupes de A consécutifs d’une longueur de deux à quatre sont renvoyés.

str_extract_all(test, "A{2,4}")
## [[1]]
## [1] "AA"   "AAA"  "AAAA"

Avec le quantificateur +, les groupes de un ou plus sont renvoyés :

str_extract_all(test, "A+")
## [[1]]
## [1] "A"    "AA"   "AAA"  "AAAA"

Relative position

Il existe des exigences spécifiques pour ce qui précéde ou suit un motif. Par exemple, pour extraire des phrases, “deux chiffres qui sont suivis d’un point” (""). (?<=\.)\s(?=[A-Z])

str_extract_all(test, "")
## [[1]]
##  [1] "A" "-" "A" "A" "-" "A" "A" "A" "-" "A" "A" "A" "A"
déclaration de position Correspond à
"(?<=b)a" Un “a” qui est précédé d’un “b”.
"(?<!b)a" “a” qui n’est PAS précédé par un “b”
"a(?=b)" “a” qui est suivi par un “b”
"a(?!b)" “a” qui n’est PAS suivi d’un “b”.

Groupes

La capture de groupes dans votre expression régulière est un moyen d’obtenir des valeurs plus organisées lors de l’extraction.

Exemples de regex

Vous trouverez ci-dessous un texte libre pour les exemples. Nous allons essayer d’en extraire des informations utiles en utilisant un terme de recherche par expression régulière.

pt_note <- "Le patient est arrivé aux urgences de l'hôpital Broward à 18h00 le 6/12/2005. Le patient s'est présenté avec une douleur abdominale irradiant du quadrant LR. La peau du patient était pâle, fraîche et moite. Sa température était de 99,8 degrés Farinheit. Le pouls du patient était de 100 bpm et filant. La fréquence respiratoire était de 29 par minute."

Cette expression correspond à tous les mots (tout caractère jusqu’à la frappe d’un non-caractère tel qu’un espace):

str_extract_all(pt_note, "[A-Za-z]+")
## [[1]]
##  [1] "Le"           "patient"      "est"          "arriv"        "aux"          "urgences"    
##  [7] "de"           "l"            "h"            "pital"        "Broward"      "h"           
## [13] "le"           "Le"           "patient"      "s"            "est"          "pr"          
## [19] "sent"         "avec"         "une"          "douleur"      "abdominale"   "irradiant"   
## [25] "du"           "quadrant"     "LR"           "La"           "peau"         "du"          
## [31] "patient"      "tait"         "p"            "le"           "fra"          "che"         
## [37] "et"           "moite"        "Sa"           "temp"         "rature"       "tait"        
## [43] "de"           "degr"         "s"            "Farinheit"    "Le"           "pouls"       
## [49] "du"           "patient"      "tait"         "de"           "bpm"          "et"          
## [55] "filant"       "La"           "fr"           "quence"       "respiratoire" "tait"        
## [61] "de"           "par"          "minute"

L’expression "[0-9]{1,2}" correspond à des nombres consécutifs de 1 ou 2 chiffres. On pourrait aussi l’écrire "\d{1,2}", ou "[:digit:]{1,2}".

str_extract_all(pt_note, "[0-9]{1,2}")
## [[1]]
##  [1] "18" "00" "6"  "12" "20" "05" "99" "8"  "10" "0"  "29"

Vous pouvez consulter une liste utile d’expressions regex et de conseils à la page 2 de cette cheatsheet.

Voir également ce tutoriel.

10.9 Resources

Une fiche de référence pour les fonctions du paquet stringr peut être trouvée ici

Une vignette sur stringr peut être trouvée ici.