.. toctree:: :maxdepth: 2 .. _grouping: Instructions groupées et structures de contrôle =============================================== 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))} ) Structures de contrôle ---------------------- 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 :func:`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" 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 .. warning:: 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. .. tip:: ``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.