Une chaîne de caractères est un morceau de texte entre guillemets. Toutes les versions de R actuellement prises en charge encodent les strings en UTF-8, ce qui permet de représenter la plupart des langues du monde.
mystring <- "some text"
mystring
#> [1] "some text"
typeof(mystring)
#> [1] "character"
Malheureusement, cette terminologie peut dérouter les programmeurs habitués à d'autres langages.
Bien que le type soit character, R ne fait aucune distinction entre une lettre isolée (appelée char dans plusieurs autres langages, mais pas en R) et une longue string.
Dans les deux cas, il s'agit d'un seul élément, que l'on peut entourer indifféremment de guillemets simples ' ' ou doubles " ".
Le guide de style recommande d'utiliser des guillemets doubles, sauf lorsque tu veux inclure des guillemets doubles à l'intérieur de la chaîne sans les échapper.
str2 <- 'String with "quotes"' # convenience format
str2
#> [1] "String with \"quotes\"" # standard format
Un character vector est donc un vecteur de strings, chaque string étant un seul élément.
s <- c("some", "strings")
s
#> [1] "some" "strings"
length(s)
#> [1] 2
length(s[1]) # the number of vector elements, not the string length
#> [1] 1
nchar(s[1]) # the number of characters in the string "some"
#> [1] 4
Dans l'exemple ci-dessus, length(s[1]) équivaut à length("some") : le nombre d'éléments du vecteur, et non la longueur de la chaîne.
Manipuler une string individuelle est évidemment possible, comme avec nchar() dans l'exemple ci-dessus, mais cela demande des fonctions particulières dont nous parlerons plus bas.
Presque tout est possible en R de base, mais beaucoup de programmeurs trouvent la prise en charge de la manipulation des strings plutôt limitée et déroutante.
Heureusement, il existe des paquets tidyverse bien plus intuitifs, flexibles et cohérents.
Il reste encore beaucoup de code hérité qui utilise les fonctions de manipulation de chaînes à l'ancienne. Cela inclut la plupart des solutions de la communauté sur Exercism.
De plus, pour de petites tâches, il peut être utile d'utiliser les fonctions natives plutôt que d'importer une grande bibliothèque. Les mainteneurs du parcours R ont tendance à adopter cette approche lorsqu'ils écrivent les solutions exemplaires qui servent à valider les exercices.
Il reste donc utile de connaître un peu les anciennes approches.
ncharRenvoie le nombre de caractères d'une string.
nchar("string")
#> [1] 6
nchar("Hrōðgār") # a person in Beowulf, written in Old English
#> [1] 7
Le sujet (complexe !) de ce que signifie « caractère » dépasse le cadre de cette page. Contentons-nous de noter quelques points dans les exemples ci-dessus :
\0 (ce qui ajouterait 1 à la longueur).paste et paste0
Combine un nombre arbitraire de strings en une seule string.
Un séparateur peut éventuellement être précisé pour paste : par défaut, c'est un espace.
paste0(v) est équivalent à paste(v, sep = "").
paste("bits", "of", "a", "string")
#> [1] "bits of a string"
paste0("bits", "of", "a", "string")
#> [1] "bitsofastring"
sprintfPour un contrôle plus fin de l'assemblage des chaînes, R reprend la fonction sprintf du C (et de plusieurs langages plus récents : Wikipédia en recense environ 30).
r <- 5.3
pi <- 3.14159
sprintf("A circle of radius %.1f has area %.2f", r, pi * r^2)
#> [1] "A circle of radius 5.3 has area 88.25"
trimwsLes espaces en début et/ou en fin de chaîne peuvent être supprimés avec trimws() :
s <- " messy string "
trimws(s)
#> [1] "messy string"
Il existe un paramètre which = "left" (ou "right") pour éviter de rogner les deux extrémités.
substrOpère sur une seule string et renvoie la sous-chaîne comprise entre deux limites (incluses).
substr("Exercism", 5, 7)
#> [1] "cis"
strsplitDécoupe une string en une liste R, à partir d'une chaîne servant de séparateur. Le séparateur est obligatoire (il n'a pas de valeur par défaut), mais peut être une chaîne vide.
strsplit("R, Python, Julia", ", ")
[[1]]
#> [1] "R" "Python" "Julia"
strsplit("Exercism", "")
[[1]]
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
Les listes seront abordées dans un concept distinct.
Si tu n'as pas encore atteint cette partie du programme, sache simplement pour l'instant que la fonction unlist() convertit (dans ce cas) une liste en vecteur.
unlist(strsplit("Exercism", ""))
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
Pour être indulgent, on pourrait dire que les fonctions de chaînes à l'ancienne ne sont pas ce que R fait de mieux (d'autres avis, moins indulgents, sont possibles).
Pour améliorer les choses, la bibliothèque stringr est en développement depuis 2009 et fait aujourd'hui partie intégrante de la collection Tidyverse.
Importe-la dans ton espace de noms avec library(stringr) ou library(tidyverse).
Voici quelques caractéristiques essentielles :
str_ et s'efforcent de rendre leur rôle évident.Comme tous les paquets du Tidyverse, stringr dispose d'une bonne documentation, généralement rédigée par les auteurs du paquet.
L'utilisation des pipes |> pour enchaîner les fonctions sera abordée plus en détail ailleurs dans le programme.
Pour l'instant, il est utile de savoir que :
L'exemple ci-dessous illustre la syntaxe. Chaque fonction sera présentée plus loin.
library(stringr)
"Monday-25-February" |>
str_split("-") |>
unlist() |> # [1] "Monday" "25" "February"
str_sub(1, 3) |> # [1] "Mon" "25" "Feb"
str_to_upper() |> # [1] "MON" "25" "FEB"
str_flatten(collapse = ", ")
#> [1] "MON, 25, FEB"
str_length compte les points de code (un peu comme nchars).
D'autres fonctions agissent sur les espaces, notamment str_trim() et str_squish().
C'est souvent une étape de nettoyage indispensable au début de tout projet de science des données.
# The first 3 kernels in JuPyteR notebooks:
str_length(c("Julia", "Python", "R")) #> [1] 1 6 5
#> [1] 5 6 1
str_pad(c("Julia", "Python", "R"), 8, "right") # add spaces if necessary
#> [1] "Julia " "Python " "R "
str_trim("Julia Python R ") # remove leading & trailing whitespace
#> [1] "Julia Python R"
str_squish("Julia Python R ") # trim, collapse multiple spaces
#> [1] "Julia Python R"
La fonction str_sub(string, start, end) renvoie la sous-chaîne allant de start à end (bornes incluses), tandis que str_sub_all() peut agir sur plusieurs chaînes.
La fonction est très souple.
start et end valent par défaut le premier et le dernier caractère, respectivement.
Ils peuvent être des vecteurs d'indices.
Contrairement à l'indexation des vecteurs, et c'est tant mieux, les valeurs négatives se comptent depuis la fin de la chaîne, à la manière de Python.
s <- "abcdefgh"
str_sub(s, 2, 4)
#> [1] "bcd"
str_sub(s, 5)
#> [1] "efgh"
str_sub(s, -3, -2)
#> [1] "fg"
str_sub(s, c(1, 4), c(2, 5))
#> [1] "ab" "de"
str_sub(s, c(1, 4, 6), c(2, 5, -1))
#> [1] "ab" "de" "fgh"
s |> str_sub(2, 4) # these functions are designed for pipes
#> [1] "bcd"
str_flatten convertit un vecteur de caractères en une seule string.
L'argument collapse est inséré entre chaque élément et vaut "" par défaut.
c("R", "Julia", "Python") |> str_flatten()
#> [1] "RJuliaPython"
c("R", "Julia", "Python") |> str_flatten(collapse = " - ")
#> [1] "R - Julia - Python"
str_c convertit plusieurs vecteurs de caractères en un seul vecteur de caractères, avec recyclage si nécessaire.
str_c(LETTERS[1:8], 1:8, sep = ":")
#> [1] "A:1" "B:2" "C:3" "D:4" "E:5" "F:6" "G:7" "H:8"
str_glue apporte à R une interpolation simple de chaînes.
Les expressions entre accolades { } sont évaluées et remplacées par leur représentation textuelle.
r <- 5.3
pi <- 3.14159
str_glue("A circle of radius {r} has area {pi * r^2}")
A circle of radius 5.3 has area 88.2472631
L'une des utilisations les plus courantes de R consiste à nettoyer des données en désordre pour les mettre dans un format cohérent en vue de leur analyse. Pour cela, il existe plusieurs façons de découper un texte en sous-chaînes. La plupart dépassent le cadre de cette page.
str_split_1 est la plus simple : elle convertit une seule string en un vecteur de morceaux, découpés selon un motif donné (il n'y a pas de motif par défaut).
s <- "R Julia Python"
str_split_1(s, " ")
#> [1] "R" "Julia" "Python"
Certains langages (surtout européens) distinguent les lettres MAJUSCULES des minuscules.
stringr propose un ensemble de fonctions pour passer de l'un à l'autre, en tenant compte de la locale :
str_to_lower()str_to_upper()str_to_title() : première lettre de chaque mot en majusculestr_to_sentence() : première lettre de la phrase en majusculestr_to_upper("elixir") # defaults to locale = "en"
#> [1] "ELIXIR"
str_to_upper("ελληνικά") # infers Greek
#> [1] "ΕΛΛΗΝΙΚΆ"
str_to_title("the cat sat on the mat")
#> [1] "The Cat Sat On The Mat"
str_to_sentence("the cat sat on the mat")
#> [1] "The cat sat on the mat"
Pour remplacer une sous-chaîne à partir d'un motif, str_replace() modifie la première occurrence du motif et str_replace_all() les modifie toutes.
Pour remplacer une sous-chaîne à partir d'indices de caractères, il existe une forme d'affectation de str_sub().
s <- "abcde"
str_sub(s, 3, 4) <- "yz"
s
#> [1] "abyze"
Dans cet exercice, on va traiter des lignes de log.
Chaque ligne de log est une string formatée comme suit : "[<LEVEL>]: <MESSAGE>".
Il existe trois niveaux de log différents :
INFOWARNINGERRORTu as trois tâches, et chacune prend une ligne de log et te demande d'en faire quelque chose.
Tu es libre d'utiliser soit les fonctions historiques de base R, soit la bibliothèque stringr, et les deux permettent d'écrire des solutions courtes et viables.
Implémente la fonction message pour renvoyer le message d'une ligne de log :
message("[ERROR]: Invalid operation")
#> "Invalid operation"
Les espaces en début et en fin doivent être supprimés :
message("[WARNING]: Disk almost full\r\n")
#> "Disk almost full"
Implémente la fonction log_level qui renvoie le niveau de log d'une ligne de log, en minuscules :
log_level("[ERROR]: Invalid operation")
#> "error"
Implémente la fonction reformat qui reformate la ligne de log, en plaçant le message en premier et le niveau de log après, entre parenthèses :
reformat("[INFO]: Operation completed")
#> "Operation completed (info)"
Inscris-toi sur Exercism pour apprendre et maîtriser R avec 21 concepts111 exercices, et un vrai mentorat humain, le tout gratuitement.