DU Bii - module 3: R and stats


Session 2: optional practical on loops, conditions and functions

Thursday 4th of March, 2021

teachers: Claire Vandiedonck & Magali Berland; helpers: Antoine Bridier-Nahmias, Yves Clément, Bruno Toupance, Jacques van Helden

Objectifs pédagogiques de ce practical qui est facultatif:

  • distinguer les boucles des exécutions conditionnelles
  • écrire des exécutions conditionnelles
  • écrire des boucles
  • comprendre que la vectorisation peut remplacer les boucles de manière avantageuse avec R
  • créer ses propres fonctions dans R et avoir saisi l'importance de l'espace clos des fonctions.

Rappels

Les exercices proposés sont donnés dans un ordre progressif qui suit celui du diaporama associé. Ils ont des niveaux de difficulté variable. Pour chaque exercice, des fonctions R vous sont suggérées. N’hésitez pas à consulter leur menu d’aide en tapant soit ?nom_fonction, soit help(nom_fonction). Vous pouvez parvenir aux mêmes résultats avec d’autres commandes. Les commandes les plus courtes sont en général les meilleures. Une correction détaillée sera fournie.

Vous pouvez réaliser ces exercices directement dans ce notebook en indiquant votre code dans les cellules laissées libres. Pour ajouter une nouvelle cellule, cliquez simplement sur le +dans le menu en haut à gauche du notebook (cf. rappels sur les notebooks en bas de ce notebook). Vous pouvez mettre plusieurs lignes de code aussi par cellule. Pour executer les cellules, cliquez sur Shift+Enter. Executez les dans le bon ordre.

Remarque: dans un notebook jupyter, par défaut chaque élément d'un vecteur est affiché séparé par un ".". Si vous souhaitez afficher le vecteur de façon plus classique, c'est à dire en ligne, tel qu'il apparait dans R, il est nécessaire d'utiliser la fonction print() -> voir dans cet exemple avec un vecteur contenant les deux valeurs numériques 1 et 10.

In [1]:
my_vector <- c(1, 10) # pour générer le vecteur et l'assigner dans un objet "my_vector"
my_vector # l'affichage ici montre deux éléments, chacun dans une ligne différente
  1. 1
  2. 10
In [2]:
print(my_vector) # L'affichage ici montre le vecteur par ligne avec l'indice 1 entre crochets indiquant l'indice de la première valeur de la ligne.
[1]  1 10

Vous pouvez également réaliser ces exercices si vous le préférez dans un terminal, une console ou rstudio.

Il est enfin possible de réaliser ces exercices sur votre ordinateur. Dans ce cas, utilisez un editeur de texte avec coloration syntaxique pour votre code (editeur dans Rstudio, ou Tinn-R ou notepad++ par exemple). Sauvegardez vos commandes dans un fichier mes_commandes.R dans le répertoire de votre choix. Exécutez les commandes une par une dans votre console. Vous pouvez ajouter des commentaires qui ne seront pas éxécutés si vous les précédez du caractère « # ».


Avant toute chose

Avant de démarrer les exercices, sauvegardez une copie de ce notebook pour backup.

1. Identifiez votre répertoire de travail

In [3]:
getwd()
'/srv/home/cvandiedonck/ue5_rsession1'

Si ce répertoire ne vous convient pas, changer le pour un répertoire existant my_directorypar exemple, avec la commande suivante en spécifiant le chemin relatif ou absolu de votre répertoire: setwd("path/my_directory")

2. Identifiez la version R de votre environnement et packages installés.

In [4]:
sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-conda_cos6-linux-gnu (64-bit)
Running under: Ubuntu 18.04.4 LTS

Matrix products: default
BLAS/LAPACK: /srv/conda/envs/notebook/lib/R/lib/libRblas.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] compiler_3.6.1  IRdisplay_0.7.0 pbdZMQ_0.3-3    tools_3.6.1    
 [5] htmltools_0.3.6 base64enc_0.1-3 crayon_1.3.4    Rcpp_1.0.1     
 [9] uuid_0.1-2      IRkernel_1.1    jsonlite_1.6    digest_0.6.18  
[13] repr_0.19.2     evaluate_0.13  


Exercice 1: tester une condition

  • Créez un vecteur de 100 valeurs tirées aléatoirement selon une loi normale de moyenne 4 et d’écart type 5.

  • Identifiez les indices des valeurs strictement supérieures à 3 et récupérez les valeurs correspondantes.

  • Testez si la somme de ces valeurs est supérieure à 40, à 30 ou à 20 et affichez un message adéquat selon chaque éventualité.

Tip :fonctions recommandées : rnorm(), which(), sum(), if(), ifelse(), else(), cat() ou print()

In [5]:
vecRandom <- rnorm(100, mean = 4, sd = 5)
In [6]:
vecAbove3 <- vecRandom[which(vecRandom > 3)]
In [7]:
valSum <- sum(vecAbove3)

if(valSum > 40){
          cat("la somme est > 40 \n")
          }else if(valSum > 30){
          cat("la somme est > 30 mais <= 40 \n")
          }else if(valSum > 20){
          cat("la somme est > 20 mais <= 30 \n")
          }else{
          cat("la somme est < ou egal 20 \n")
}
la somme est > 40 

=> Pour aller plus loin:

vous pouviez aussi obtenir le vecteur vecAbove3 avec la fonction ifelse():

In [8]:
identical(vecRandom[ifelse(vecRandom >3, TRUE, FALSE)] , vecRandom[which(vecRandom > 3)]) # exemple ici où je compare en plus si le résultat est bien le même
TRUE

Exercice 2: création d'une boucle simple

  • Créez une boucle de 10 itérations i qui affiche à chaque itération l’indice i.
  • Calculez au fur et à mesure la somme cumulée des indices dans un vecteur.
  • Affichez la somme cumulée finale.

Tip : fonction recommandée : for(), cat() ou print()

In [9]:
sumCumul <- 0 # initiate the vector

for(i in 1:10){
  print(i) # always print the index of the result, we might prefer cat(), see below
  sumCumul <- sumCumul + i
  cat(paste("for i:", i, "  ,the sumCumul is: ", sumCumul, "\n", sep=""))
}
[1] 1
for i:1  ,the sumCumul is: 1
[1] 2
for i:2  ,the sumCumul is: 3
[1] 3
for i:3  ,the sumCumul is: 6
[1] 4
for i:4  ,the sumCumul is: 10
[1] 5
for i:5  ,the sumCumul is: 15
[1] 6
for i:6  ,the sumCumul is: 21
[1] 7
for i:7  ,the sumCumul is: 28
[1] 8
for i:8  ,the sumCumul is: 36
[1] 9
for i:9  ,the sumCumul is: 45
[1] 10
for i:10  ,the sumCumul is: 55
In [10]:
# affichage de la somme cumulee finale
print(sumCumul)
[1] 55

Exercice 3: création d'une fonction

  • Créez une fonction calculSomme qui calcule la somme de deux variables x et y passées en argument.
  • Testez la fonction.

Tip :fonction recommandée : function(), return()

In [11]:
calculSomme <- function(x, y){
    return(x + y)
}

-> Test de la fonction avec par exemple 18 et 35:

In [12]:
calculSomme(x = 18, y = 35)
53

=> Pour aller plus loin:

Si vous voulez, vous pouvez definir avant un vecteur qui contiendra le resultat de la somme

In [13]:
sum_xandy <- NULL
calculSomme <- function(x, y){
  sum_xandy <- x+y
  return(sum_xandy)
}
sum_xandy <- calculSomme(x = 18, y = 35) # le resultat est stocké dans l'objet sum_xandy qui n'est plus NULL
sum_xandy # affichez le resultat
53

Si maintenant, vous voulez répeter l'operation et stocker les resultats dans un vecteur, il faut concatener les resultats dans un vecteur

In [14]:
sum_xandy <- NULL
calculSomme <- function(x, y){
  sum_xandy <- c(sum_xandy, x+y)
  return(sum_xandy)
}
sum_xandy <- calculSomme(x = 18, y = 35)
sum_xandy <- calculSomme(x = 20, y = 35)
sum_xandy <- calculSomme(x = 18, y = 3)
# le resultat est stocke dans l'objet sum_xandy qui n'est plus NULL
print(sum_xandy)
[1] 53 55 21

Exercice 4: création d’une fonction avec des tests, utilisation de cette fonction de manière itérative

  • Ecrivez une fonction calculTarif() qui prend pour argument un âge et affiche “demi-tarif” si l’âge est inférieur à 12 ans, “tarif sénior” si l’âge est supérieur ou égal à 60 ans et “plein tarif” sinon.
  • Testez votre fonction pour des personnes de 5, 65, 85, 41, 23 et 47 ans.

Tip :fonctions recommandées : function(), return(), print(), c(), if(), else(), ifelse(), for()

In [15]:
calculTarif <- function(age){
    if(age < 12){
        print("tarif reduit")
    }else if(age >= 60){
        print("tarif senior")
    }else{
        print("plein tarif")
    }
}

-> test de la fonction

In [16]:
for(i in c(5, 65, 85, 41, 23, 47)){
    calculTarif(age = i)
}
[1] "tarif reduit"
[1] "tarif senior"
[1] "tarif senior"
[1] "plein tarif"
[1] "plein tarif"
[1] "plein tarif"

Exercice 5: création d’une fonction avec compteur de boucle

  • Ecrivez une fonction sumCumul() qui calcule la somme cumulée des nombres entiers compris entre deux bornes a et b que vous mettrez en arguments start et end.

  • De plus, toutes les 10 boucles, vous affichez la valeur de l’entier ajouté, sinon vous affichez un point ..

  • Testez la fonction avec les entiers entre 3 et 55 par exemple.

  • Améliorez la fonction en ajoutant un paramètre "interval" correspondant à l’incrément de boucles entre les affichages des entiers (dans la fonction précédente, cet incrément était de 10)

  • Testez la fonction avec les entiers entre 3 et 55 et un intervalle de 15 par exemple.

Tip :fonctions recommandées : function(), return(), cat(), seq()

In [17]:
sumCumul <- function(start,end){
         temp <- 0
         for(i in start:end){
               temp <- temp + i
               if (i %in% seq(start,end,10)){
                  cat(i)
                  }
                  else {cat(".")}
         }            
         cat("\n")
         cat(paste("le total cumule est de: "), temp, "\n",sep="")
         return(temp)
}

-> test de la fonction avec les entiers 3 et 55:

In [18]:
res <- sumCumul(3,55)
3.........13.........23.........33.........43.........53..
le total cumule est de: 1537

=> Pour aller plus loin:

Voici la fonction ameliorée avec un intervalle en argument:

In [19]:
sumCumul <- function(start,end, interval){
         temp <- 0
         for(i in start:end){
               temp <- temp + i
               if (i %in% seq(start,end,interval)){
                  cat(i)
                  }
                  else {cat(".")}
         }            
         cat("\n")
         cat(paste("le total cumule est de: "), temp, "\n",sep="")
         return(temp)
}
In [20]:
res <- sumCumul(3,55,15)
3..............18..............33..............48.......
le total cumule est de: 1537
In [21]:
res <- sumCumul(3,55,20)
3...................23...................43............
le total cumule est de: 1537


Rappels sur l'utilisation des notebooks

  • To add a new cell, click on the "+" icon in the toolbar menu*
  • You can "click & drag" to move up or down a cell*
  • Cells are either 'Code cells' or 'Markdown cells'*
  • To execute a 'Code cell', press SHIFT+ENTER*
  • To format a 'Markdown cell', press SHIFT+ENTER*
  • To modify a 'Markdown cell', double-click on it*