R avancé et introduction à Git

Raphaël Nedellec

IDE : RStudio

En résumé :

  1. Utilisez des projets !
  2. Apprenez les raccourcis claviers (Alt+Maj+K sous Windows).
  3. Devenez familier avec votre outil de travail. Le temps investi ne sera pas perdu !
  4. Configurez les options globales.

Options à configurer recommandées

  • General>Basic: Restore .RData into workspace at startup: No
  • General>Basic: Save workspace to .RData on exit: Never
  • Code>Saving>Serialization: Default text encoding: UTF-8

Rappels de R

Objets

En R, tout est objet.

Un objet est l’association d’un nom et d’une valeur. Techniquement, on associe une valeur à un nom.

nom <- "valeur"

Plusieurs opérateurs pour affecter une valeur :

nom = "valeur"
"valeur" -> nom

Contrainte sur les noms : ils ne peuvent commencer par un _ ou un chiffre.

Types primitifs

Il existe 6 types primitifs en R

character, integer, numeric, logical,

charactere <- "abcdef"
entier     <- 1L
numerique  <- 1.1
booleen    <- TRUE

ainsi que deux types plus rares, raw et complex.

Warning

Toujours utiliser les valeurs TRUE et FALSE pour les valeurs logiques, et non les écritures raccourcies T et F.

T <- F # est possible !!
TRUE <- FALSE # error

Types primitifs

Fonctions de coercition de type (type coercion) : as.*

as.numeric("1.2")
#> [1] 1.2
as.character(2.3)
#> [1] "2.3"
as.integer(TRUE)
#> [1] 1

Fonctions d’assertion de type : is.*

is.numeric(1.23)
#> [1] TRUE
is.numeric(1L)
#> [1] TRUE
is.numeric("1.23")
#> [1] FALSE

Autres objets importants

Facteur (factor) :

factor(c("a", "b", "b", "c"), levels = c("a", "b", "c", "d"))
#> [1] a b b c
#> Levels: a b c d

Facteur ordonné (ordered) :

factor(c("a", "b", "b", "c"), 
      levels = c("a", "b", "c", "d"),
      ordered = TRUE)
#> [1] a b b c
#> Levels: a < b < c < d

Mais aussi Date, POSIXct, POSIXlt, data.frame, matrix, array

Vecteurs

Les vecteurs sont omniprésents en R. Il en existe deux types :

  • atomiques : logical, integer, numeric, character
  • listes: list

Les vecteurs peuvent être équipés d’attibuts :

vecteur <- 1:4
attr(vecteur, "a") <- "hello"
attr(vecteur, "b") <- "you!"

# ou de manière équivalente
vecteur2 <- structure(
  1:4,
  a = "hello",
  b = "you!"
)

Vecteurs

Pour créer un vecteur de type atomique :

vecteur_double     <- c(1, 2.3, 4.5, -6.6)
vecteur_entier     <- c(1L, 2L, 22L)
vecteur_charactere <- c("ceci", "est", "un vecteur")

Pour créer une liste :

liste <- list(
  a = c(1, 2.3, 4.5, -6.6),
  b = c(1L, 2L, 22L),
  c = c("ceci", "est", "un vecteur")
)

Chaque élément d’une liste peut être d’un type différent, contrairement aux vecteurs atomiques.

Vecteurs

Certains attributs de vecteurs sont très communs et très importants :

  • dim
  • names
  • class

Objets S3

Nous détaillerons la notion d’objets S3 lors du second cours

Subsetting

  • Il y a 6 façons d’extraire un sous-ensemble (subsetting) d’un vecteur atomique.
  • Il y a 3 opérateurs d’extraction d’un sous-ensemble (subset), [[, [, et $.
  • Ces opérateurs interagissent différemment avec les différents types de vecteurs : atomiques, listes, facteurs, matrices, data.frames.
  • L’extaction d’un sous-ensemble peut être combinée avec l’assignation.

Subsetting

L’opérateur [ permet de sélectionner plusieurs éléments d’un vecteur.

x <- c(2.1, 4.2, 3.3, 5.4)
x[c(1, 3)]
x[-c(1, 3)]
x[c(TRUE, TRUE, FALSE, FALSE)]
x[]
x[0]
x <- setNames(x, c("a", "b", "c", "d"))
x[c("a", "c")]

Subsetting

L’opérateur [ permet de sélectionner plusieurs éléments d’un vecteur.

x <- c(2.1, 4.2, 3.3, 5.4)
x[c(1, 3)]
x[-c(1, 3)]
x[c(TRUE, TRUE, FALSE, FALSE)]
x[]
x[0]
x <- setNames(x, c("a", "b", "c", "d"))
x[c("a", "c")]
#> [1] 2.1 3.3
#> [1] 4.2 5.4
#> [1] 2.1 4.2
#> [1] 2.1 4.2 3.3 5.4
#> numeric(0)
#>   a   c 
#> 2.1 3.3

Subsetting

Pour des listes :

  • l’opérateur [ renvoie toujours une liste
  • l’opérateur [[ renvoie un élément de la liste
  • l’opérateur $ renvoie un élément de la liste si la liste est nommée

Subsetting

Subsetting

Control Flow

  • Choix : if, else, else if, ifelse, switch
  • Boucles : for, while, repeat
  • Opérateurs spéciaux : next, break

Mots réservés

Tous les noms ci-dessus sont des noms réservés par R et ne peuvent pas être utilisés pour nommer un objet, tout comme function, NA, Inf, etc. Voir ?reserved.

Programmation fonctionnelle

Nous verrons lors du second cours l’introduction des fonctions *apply ou map_* qui sont complémentaires aux boucles for.

Choix

# condition: vecteur logique de taille 1
a <- if (condition) 1 else 2
# if / else if / else
if (b == "a") {
  a <- ".."
} else if (b == "b") {
  a <- "autre chose"
} else {
  stop("error")
}
# switch
switch(b,
       a = "..",
       b = "autre chose",
       stop("error"))
# ifelse vectorisé
ifelse(test = c(TRUE, TRUE, FALSE), "a", "b")

Boucles : For

for (i in 1:3) {
  # ...
  print(i)
}
#> [1] 1
#> [1] 2
#> [1] 3

Contrairement à une croyance répandue, les boucles for ne sont pas spécialement lentes. Il faut penser à pré-allouer un vecteur à la taille des résultats attendus.

# mauvais
x <- c()
for (k in 1:10) {
  x <- c(x, k)
}

# bon
x <- numeric(10L)
for (k in 1:10) {
  x[[k]] <- k
}

Boucles : while, repeat, next, break

# while : tant que la condition 
# est vraie, on continue
x <- 0L
while (x <= 5L) {
  x <- x + 1L
  if (x %% 2L == 0L) next
  print(x)
}
# repeat : autant que nécessaire
x <- 0L
repeat {
  x <- x + 1L
  if (x == 6L) break
  if (x %% 2L == 0L) next
  print(x)
}

Boucles : while, repeat, next, break

# while : tant que la condition 
# est vraie, on continue
x <- 0L
while (x <= 5L) {
  x <- x + 1L
  if (x %% 2L == 0L) next
  print(x)
}
#> [1] 1
#> [1] 3
#> [1] 5
# repeat : autant que nécessaire
x <- 0L
repeat {
  x <- x + 1L
  if (x == 6L) break
  if (x %% 2L == 0L) next
  print(x)
}
#> [1] 1
#> [1] 3
#> [1] 5

Tips

  • break stoppe les itérations
  • next permet de passer à l’itération suivante

Fonctions

Les fonctions permettent d’automatiser et de mutualiser des tâches courantes.

addition <- function(x, y) {
  return(x + y)
}
addition(1, 2)
#> [1] 3

Fonctions, fonctions génériques

Nous détaillerons le fonctionnement et les bonnes pratiques d’écriture des fonctions lors du second cours.

Librairies

Pour charger une librairie externe, nous utilisons la fonction library()

library(dplyr) # chargement explicite de la libraire dplyr
  • CRAN : répertoire et archive historique de la communauté R
  • tidyverse : collection de librairies développées par RStudio/Posit
  • rOpenSci : consortium pour une science ouverte

Package

Nous détaillerons comment construire un package lors du troisième cours.

Librairies

Attention

Attention, tous les packages ne sont pas de qualité égale. Certains peuvent même être potentiellement dangereux et corrompus. Il faut apprendre à détecter des librairies peu fiables.

L’enfer des dépendances

Les librairies externes facilitent et accélèrent grandement les études, mais créent aussi des vulnérabilités et des dépendances.

Info

Nous nous intéresserons à la gestion propre des dépendances lors du 4ème cours.

Aide et fonctions utiles

Documentation R

La fonction la plus importante de R : ?

?help
?str

Voir aussi rdocumentation.org

Inspecter un objet R

Fonction str()

data(mtcars)
str(mtcars)
#> 'data.frame':    32 obs. of  11 variables:
#>  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#>  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
#>  $ disp: num  160 160 108 258 360 ...
#>  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
#>  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
#>  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
#>  $ qsec: num  16.5 17 18.6 19.4 17 ...
#>  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
#>  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
#>  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
#>  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
str(mtcars$mpg)
#>  num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...

Demander de l’aide

Si vous rencontrez un problème, il existe avec une très grande probabilité quelqu’un l’ayant déjà rencontré et ayant posté un message sur Internet. Et il est probable que la solution existe aussi !

Apprendre à lire un message d’erreur

x <- c(TRUE, FALSE)
if (x) {
  print("hello")
}

Apprendre à lire un message d’erreur

x <- c(TRUE, FALSE)
if (x) {
  print("hello")
}
#> Error in if (x) {: the condition has length > 1

Parfois, le message n’est pas très “grand public”

data <- data[[0L]]
file <- read.csv("file_which_doesnt_exist.csv")

Apprendre à lire un message d’erreur

x <- c(TRUE, FALSE)
if (x) {
  print("hello")
}
#> Error in if (x) {: the condition has length > 1

Parfois, le message n’est pas très “grand public”

data <- data[[0L]]
#> Error in data[[0L]]: object of type 'closure' is not subsettable
file <- read.csv("file_which_doesnt_exist.csv")
#> Error in file(file, "rt"): cannot open the connection

Il est normal de faire des erreurs

Toujours prendre le temps de lire le message d’erreur, faire une recherche google associée… Un bug arrive rarement et les erreurs sont souvent stupides : typo, mauvais nom de variable, etc.

Bonnes pratiques

Conventions de codes

  • Le code est à destination de l’ordinateur - il doit être interprété par R mais aussi de vos collègues humains. Il faut respecter des conventions.
  • Conventions de nommage de variables, de fonctions
  • Règles syntaxiques
  • Bonnes pratiques

Guide de style de référence : https://style.tidyverse.org/index.html

linter

Contrôlez la qualité de votre code en utilisant un linter, par exemple, lintr

a=2
b <-2*2
f <- function(a,b) {a+b}

linter

Contrôlez la qualité de votre code en utilisant un linter, par exemple, lintr

lintr

S’intègre bien avec RStudio, il exite un addin. Le linter est aussi un outil utile pour la vérification automatique de code, notamment dans un processus d’intégration continue. Plus là dessus dans le cours n°5.

styler

Corrigez automatiquement certaines erreurs de style, avec la librarie styler

f<-function(a,b,c) {
#commentaire sans espace
  res= a*b+ c
   res<-res*2
  final= if(TRUE) {res} else {
    "else"}
  return( final)
}

styler

Corrigez automatiquement certaines erreurs de style, avec la librarie styler

f <- function(a, b, c) {
  # commentaire sans espace
  res <- a * b + c
  res <- res * 2
  final <- if (TRUE) {
    res
  } else {
    "else"
  }
  return(final)
}

styler

Complémentaire du linter. Aussi en addin dans RStudio.

Questions ?