14. Instructions groupées et structures de contrôle
14.1. Expressions groupées
R est un langage qui évalue les expressions qui lui sont fournies et retourne un résultat:
> c(1, 2, 3)
[1] 1 2 3
On peut affecter le résultat de l’évaluation d’une expression à une variable pour réutilisation ultérieure:
> v <- c(1, 2, 3)
Les expressions peuvent être groupées entre accolades {
}
. Chacune des instructions élémentaires est exécutée. La valeur retournée est le résultat de la dernière expression du groupement:
> { x <- c(1, 2, 3) ; y <- c(4, 5, 6) ; c(7, 8, 9) }
[1] 7 8 9
> x
[1] 1 2 3
> y
[1] 4 5 6
Un autre exemple:
> sample_stats <- {
+ sample <- rnorm(1000, 5, 10)
+ stats <- c(mean(sample), median(sample), var(sample))
+ }
> head(sample)
[1] 3.848532 -1.208626 14.149470 14.088703 -13.269124 -6.111380
> stats
[1] 4.758661 4.716693 103.390498
> sample_stats
[1] 4.758661 4.716693 103.390498
Les expressions groupées sont utiles pour exécuter plusieurs tâches lorsque la syntaxe d’une fonction requiert une seule expression:
> with(titanic, { print(head(Joined)) ; print(tail(Age))} )
14.2. Structures de contrôle
14.2.1. Exécution conditionnelle
En R, l’exécution conditionnelle possède la structure suivante:
> if (expr_1) expr_2 else expr_3
expr_1
doit être une simple valeur logique. expr_2
et expr_3
peuvent être des instructions simples ou groupées.
Here is a basic example:
> x <- -2
> if (x >=0) sign_of_x <- "positive" else sign_of_x <- "negative"
> sign_of_x
[1] "negative"
> x <- 2
> if (x >=0) sign_of_x <- "positive" else sign_of_x <- "negative"
> sign_of_x
[1] "positive"
On peut utiliser le fait que l’évaluation d’une expression groupée est le résultat de l’évaluation de la dernière expression:
> x <- -2
> sign_of_x <- if (x >=0) {"positive"} else {"negative"}
> sign_of_x
[1] "negative"
> x <- 2
> sign_of_x <- if (x >=0) {"positive"} else {"negative"}
> sign_of_x
[1] "positive"
L’exécution conditionnelle possède également un else if
:
if ( test_expression1) {
statement1
} else if ( test_expression2) {
statement2
} else if ( test_expression3) {
statement3
} else
statement4
Les opérateurs logiques &&
et ||
sont utilisés pour construire des prédicats complexes:
> sign_of_x <- if (x >0 || x==0) {"positive"} else {"negative"}
Important
Les opérateurs &
and |
appliquent les conditions logiques sur des vecteurs de dimension supérieure à 1, élément par élément. alors que &&
et ||
sont utilisés avec des scalaires (vecteurs de longueur 1). Le second opérande n’est évalué que si nécessaire.
La fonction ifelse()
est une version vectorisée de la construction if/else
. Elle est de la forme ifelse(condition, a, b)
et retourne un vecteur logique de taille, la longueur du plus long vecteur passé en argument. Il est évalué à a[i]
si condition[i]
est TRUE, à b[i]
sinon:
> ifelse(c(-1,0,1) >=0, "positive", "negative")
[1] "negative" "positive" "positive"
14.2.2. Répétition d’instructions: for
, repeat
et while
On peut implémenter la répétition d’instructions avec une syntaxe de la forme:
> for (name in expr_1) expr_2
name
est la variable de boucle, expr_1
retourne un vecteur, et expr_2
est souvent une expression groupée de plusieurs instructions. expr_2
est évaluée autant de fois que nécessaire pour chaque valeur de name
prise séquentiellement dans le vecteur expr_1
.
Here is a very basic example:
> for(i in 1:5){
+ sq <- i*i
+ print(c(i,sq))
+ }
[1] 1 1
[1] 2 4
[1] 3 9
[1] 4 16
[1] 5 25
Avertissement
R étant un langage vectorisé, les boucles for
sont utilisés de façon beaucoup moins fréquentes que dans d’autres langages. La vectorisation permet une écriture plus compacte et plus lisible (et donc une plus grande maintenabilité) et également une exécution plus rapide. L’utilisation de boucles for
inutiles est un signe de mauvaise appropriation du langage.
On peut également répéter des instructions avec while
selon la syntaxe while (condition) expr
. Par rapport à la boucle for
, il faut :
préciser l’affectation intiale de la variable de boucle
gérer l’évolution de la variable de boucle
On utilisera ce type de construction lorsque l’ensemble des valeurs à parcourir n’est pas connu à l’entrée de la boucle.
L’exemple précédent réécrit avec une boucle while
:
> i <- 1
> while ( i<=5) {
+ sq <- i*i
+ print(c(i,sq))
+ i <- i+1
+ }
[1] 1 1
[1] 2 4
[1] 3 9
[1] 4 16
[1] 5 25
R dispose également de repeat
, utilisé avec la syntaxe repeat expr
:
> i <- 1
> repeat {
+ sq <- i*i
+ print(c(i,sq))
+ i <- i+1
+ if (i>5) break
+ }
[1] 1 1
[1] 2 4
[1] 3 9
[1] 4 16
[1] 5 25
On utilise break
pour terminer la boucle.
Astuce
while
et repeat
fonctionnent de façon très similaire. La différence entre les deux est que while
évalue la condition de continuation au début de la boucle alors que repeat
l’évalue à la fin. Une autre différence est que repeat
nécessite l’emploi explicite de break
pour terminer la boucle.