R propose un ensemble d'opérateurs identiques à ceux de bien d'autres langages :
1 == 2 # FALSE
1 != 2 # TRUE
1 < 2 # TRUE
1 > 2 # FALSE
1 <= 2 # TRUE
1 >= 2 # FALSE
La forme de base d'un if-then-else est la suivante :
if (x > 10) {
y <- "big"
} else if (x > 2) {
y <- "medium"
} else {
y <- "tiny"
}
Dans ce cas, les parenthèses ( ) autour du booléen et les accolades { } autour du corps sont toutes deux obligatoires.
Une instruction if simple peut s'écrire plus court :
if (x == 0) return("success")
En anticipant le concept vector-filtering : la clause conditionnelle entre parenthèses () doit s'évaluer en une seule valeur TRUE/FALSE.
Si l'on inclut des vecteurs dans la comparaison, on obtient généralement un vecteur de booléens ; il faut alors l'envelopper dans une fonction d'agrégation comme all() (toutes les valeurs sont-elles TRUE ?) ou any() (au moins une valeur est-elle TRUE ?).
numbers <- c(4,5,7,9,10,11)
numbers %% 3 == 0 # gives vector of booleans
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE
# use any() to get a single TRUE/FALSE
if (any(numbers %% 3 == 0)) print("1 or more numbers are divisible by 3")
#> [1] "1 or more numbers are divisible by 3"
ifelse
Une autre forme de if-else peut être utile, à condition qu'il n'y ait qu'un résultat vrai/faux.
y <- ifelse(x > 8, "big", "small")
# Don't mix result types:
z <- ifelse(x > 100, 100, "small") # numeric or string result? Expect problems!
ifelse() prend exactement trois paramètres :
TRUE
FALSE.Les entrées vectorielles sont acceptées, et l'on obtient alors un vecteur en sortie.
Dans ce cas, veille à ce que les deux branches produisent le même type de données : numérique, caractère, logique, etc.
Nous verrons cela dans le concept vector-functions.
Les deux résultats ("big", "small" dans l'exemple ci-dessus) doivent être des valeurs uniques.
Malheureusement, si tu donnes un vecteur plus long, R fera probablement quelque chose de déroutant et d'inattendu, sans émettre le moindre message d'avertissement.
if_else
Les mainteneurs du langage R ont pour politique d'éviter autant que possible les ruptures de compatibilité. Cela permet de préserver le nombre considérable de packages tiers disponibles sur CRAN, mais limite la possibilité de mettre à jour le R de base avec des concepts de programmation modernes.
Ces dernières années, plusieurs packages ont vu le jour ; ils étendent et parfois remplacent les fonctionnalités de R, forts de plusieurs décennies d'expérience sur les forces et les faiblesses de la conception initiale de R.
Ces packages forment la collection tidyverse.
Ils ont été ajoutés à l'exécuteur de tests d'Exercism en 2023 et sont à ta disposition dans les exercices.
Notre parcours R précède de plusieurs années l'ajout de la tidyverse, tu remarqueras donc peut-être que beaucoup de solutions de la communauté s'en tiennent au langage de base.
dplyr
dplyr sert surtout à manipuler des dataframes (nous verrons cela plus loin dans le cours).
Ajoute-le avec library(dplyr) en haut de ton code, ou library(tidyverse) pour charger toute la collection.
Tu verras peut-être des messages d'avertissement à propos de noms masqués, mais c'est rarement un problème.
Pour le concept qui nous intéresse, la fonction if_else mérite d'être mentionnée.
Elle est très proche de ifelse dans le R de base.
library(dplyr) # warnings not shown
x <- 10
if_else(x > 8, "big", "small")
#> [1] "big"
La principale différence est que if_else peut prendre un quatrième argument facultatif, pour les valeurs manquantes que R représente par NA.
xs <- c(3, NA, 10, NA, 4) # a 5-element vector
xs
#> [1] 3 NA 10 NA 4
if_else(xs > 8, "big", "small", "missing")
#> [1] "small" "missing" "big" "missing" "small"
# contrast:
ifelse(xs > 8, "big", "small")
#> [1] "small" NA "big" NA "small"
Tu trouveras peut-être aussi que if_else donne des messages d'erreur bien meilleurs que l'ancien ifelse.
Après avoir chargé la bibliothèque dplyr, tu auras aussi accès à la fonction between().
R n'autorise pas l'enchaînement des comparaisons, donc 1 <= x <= 5 renverra un message d'erreur.
Une fois dplyr chargé, between(x, 1, 5) équivaut à x >= 1 & x <= 5, et se lit peut-être plus facilement.
Les bornes inférieure et supérieure sont toutes deux incluses.