Pour exécuter la totalité du code R proposé dans ce document, il est nécessaire d’installer les packages R suivants :

ade4, plyr, lme4, lattice, ggplot2, rbenchmark, microbenchmark, proftools, profvis, Rcpp

back to top

1 L’écosystème de R

1.1 C’est quoi R ?

  • R est un langage dérivé du langage S, interprété (en opposition aux langages compilés), non typé.
  • R est un logiciel libre (sous licence GNU GPL), gratuit, multiplateforme.
  • R est orienté vers le traitement des données et l’analyse statistique.

  • Le projet R naît en 1993, se structure en 1997 et la version 1.0.0 est publiée en 2000.
  • La R Core Team est un groupe d’une vingtaine de personnes au cœur du développement du langage R.
  • R est essentiellement codé en C, R et Fortran.

  • De très nombreux utilisateurs à travers le monde.
  • Appliqué dans un grand nombre de disciplines.
  • Un large essor dans le monde académique mais aussi dans les entreprises privées.
  • Conférences annuelles :
    • UseR, la prochaine à Brisbane, en Australie, du 10 au 13 juillet 2018.
    • Rencontres R, la prochaine à Rennes, du 4 au 6 juillet 2018.
  • Le R Journal paraît deux fois par an et les article sont en accès libre et soumis à un comité de lecture.

1.2 C’est quoi un package (library) R ?

  • Un package est l’unité fondamentale de code partageable dans R.
  • Un package peut contenir du code et/ou des données, de la documentation, des tests.
  • 30 packages recommandés sont automatiquement distribués lors de l’installation de R.
  • Le dépôt officiel de packages R est le CRAN (The Comprehensive R Archive Network).
  • Plus de 12000 packages existent sur CRAN (mars 2018).


Evolution du nombre de packages depuis 1998 (Smith 2017)


  • Le dépôt CRAN de packages est déployé à travers le monde via les miroirs locaux.1
  • Bioconductor est un autre dépôt officiel de packages R dédiés aux problématiques bioinformatiques.
  • Tout le monde peut proposer un nouveau package pour valoriser et partager ses méthodes, ses codes, ses données.
  • De nombreuses contraintes pour créer et soumettre son propre package (R Core Team 2018b ; Wickham 2015b)
  • … mais qui facilitent largement l’installation et l’exploration de nouveaux packages, accessibles en open-source, par les utilisateurs.


Deux commandes essentielles pour installer et utiliser de nouveaux packages dans R : {#custom}

  • install.packages("nomPkg") pour installer le package nomPkg localement sur sa machine.
  • library(nomPkg) pour charger les fonctionnalités dans sa session R. Cette commande doit être exécutée à chaque nouvelle session (sauf si vous avez sauvegardé votre session).
# installer le package qui se nomme 'ade4', depuis le miroir situé à Lyon 1
install.packages("ade4", repos = "https://pbil.univ-lyon1.fr/CRAN/")
# charger le package 'ade4' dans la session R en cours
library(ade4)

1.3 Quels outils pour R ?

1.3.1 Des outils pour développer

Dans le cadre des bonnes pratiques de développement informatique, il est recommandé de s’appuyer sur un IDE (Integrated Development Environment) pour construire ses projets de développement informatique.

Concernant R, il existe plusieurs IDE dédié à ce langage :

1.3.2 Des outils pour partager

Au sein de nos structures (Université, CNRS, autres EPST), il nous est demandé de préférer les outils institutionnels pour héberger les projets de développement informatiques. Il existe de nombreux serveurs institutionnels qui permettent d’héberger et de partager des projets R, chaque solution ayant ses particularités, ses défauts et ses avantages. Entre autres, sont disponibles :

  • SourceSup : forge portée par le réseau RENATER qui permet d’héberger des projets versionnés avec git et Subversion.
  • Gitlab IN2P3 : serveur GitLab hébergé au centre de calcul de l’IN2P3, à Lyon, qui permet d’héberger des projets versionnés avec git, auquel il est possible de se connecter via Shibboleth.
  • Au sein même de nombreux labos, notamment ceux qui possèdent des ressources informatiques (matériel et personnel) performantes.

Côté grand public, il existe principalement deux plateformes d’hébergement :

1.4 Commencer dans R

1.4.1 Fichiers et répertoire de travail

  • Une session R peut être définie par l’environnement global en cours dans lequel se trouvent des packages, fonctions, données, variables importées ou créées.
  • Une session R peut être sauvegardée pour être chargée plus tard ou ailleurs :
    • l’environnement est sauvé dans un fichier qui se nomme .RData
    • l’historique des commandes utilisées dans la session est sauvé dans un fichier qui se nomme .Rhistory
  • Un script avec une extension .R permet de sauver les étapes qui ont conduit à la création des objets.
  • De manière pratique, on travaille, d’un côté avec un éditeur dans lequel on peut modifier son script R et d’un autre côté, une invite de commande dans laquelle on accède à sa session R.

  • On peut connaître le répertoire dans lequel est ouvert la session R en cours, grâce à la commande getwd().
  • On peut se déplacer dans un autre répertoire avec la commande setwd("/chemin/du/repertoire/que/je/veux").
  • La commande .libPaths() permet de savoir dans quel répertoire sont localisés les packages installés.
  • La commande sessionInfo() peut être utile pour avoir des informations sur la session R en cours (version de R, plateforme, variables locales, packages attachés et chargés).

# afficher le répertoire courant de travail
getwd()
## [1] "/home/aursiber/Bureau/2018_R_LyonCalcul"
# afficher les répertoires dans lesquels R va chercher les packages
.libPaths()
## [1] "/home/aursiber/R/x86_64-pc-linux-gnu-library/3.4"
## [2] "/usr/share/R-3.4.0/library"
# afficher des informations sur la session R en cours
sessionInfo()
## R version 3.4.0 (2017-04-21)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.3 LTS
## 
## Matrix products: default
## BLAS: /usr/share/R-3.4.0/lib/libRblas.so
## LAPACK: /usr/share/R-3.4.0/lib/libRlapack.so
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] ade4_1.7-10
## 
## loaded via a namespace (and not attached):
##  [1] MASS_7.3-47     compiler_3.4.0  backports_1.1.1 magrittr_1.5   
##  [5] rprojroot_1.2   tools_3.4.0     htmltools_0.3.6 yaml_2.1.14    
##  [9] Rcpp_0.12.16    stringi_1.1.7   rmarkdown_1.8   knitr_1.20     
## [13] stringr_1.3.0   digest_0.6.15   evaluate_0.10.1

1.4.2 Support et aide

  • Le nom du logiciel ne facilite pas les recherches sur le web.
  • Mais la communauté des utilisateurs est mature et très active.
  • Beaucoup de supports de formation, de documents disponibles, de forums, …

La documentation officielle de R

Se documenter dans R

  • Si vous savez ce que vous cherchez et son nom (un package, une fonction, un jeu de données).
  • L’objet R recherché doit appartenir à un package, celui-ci étant déjà installé sur votre machine.
  • Dans une session R, ?nomFctn ou help("nomFctn").
  • Chaque objet d’un package est illustré grâce à un exemple, celui-ci pouvant être exécuté avec la commande example(nomFctn).
  • Certains packages possèdent également un guide d’utilisation plus poussé, appelé vignette, accessible par la commande vignette("nomPkg").
# obtenir des informations sur le package 'ade4'
help("ade4-package")

# obtenir des informations sur la fonction 'dudi.pca'
?dudi.pca
# help("dudi.pca")

D’autres documentations généralistes

1.4.3 Bien citer R

Les commandes citation() et citation("nomPkg") retournent, respectivement, la manière dont les développeurs souhaitent que les utilisateurs citent R et leur package dans les publications qui ont nécessité leur usage.

# citer le logiciel R
citation()
## 
## To cite R in publications use:
## 
##   R Core Team (2017). R: A language and environment for
##   statistical computing. R Foundation for Statistical Computing,
##   Vienna, Austria. URL https://www.R-project.org/.
## 
## A BibTeX entry for LaTeX users is
## 
##   @Manual{,
##     title = {R: A Language and Environment for Statistical Computing},
##     author = {{R Core Team}},
##     organization = {R Foundation for Statistical Computing},
##     address = {Vienna, Austria},
##     year = {2017},
##     url = {https://www.R-project.org/},
##   }
## 
## We have invested a lot of time and effort in creating R, please
## cite it when using it for data analysis. See also
## 'citation("pkgname")' for citing R packages.
# citer le package 'ade4'
citation("ade4")
## 
## To cite ade4 in publications use one these references:
## 
##   Dray, S. and Dufour, A.B. (2007): The ade4 package: implementing
##   the duality diagram for ecologists. Journal of Statistical
##   Software. 22(4): 1-20.
## 
##   Chessel, D. and Dufour, A.B. and Thioulouse, J. (2004): The ade4
##   package-I- One-table methods. R News. 4: 5-10.
## 
##   Dray, S. and Dufour, A.B. and Chessel, D. (2007): The ade4
##   package-II: Two-table and K-table methods. R News. 7(2): 47-52.
## 
## To see these entries in BibTeX format, use 'print(<citation>,
## bibtex=TRUE)', 'toBibtex(.)', or set
## 'options(citation.bibtex.max=999)'.

back to top

2 Les bases du langage R

2.1 Les données

2.1.1 Importer et exporter des données

Importer des données

Ici, sont présentées les fonctions les plus couramment utilisées. Il existe d’autres commandes adaptées à des données plus spécifiques (données spatiales, données génomiques, données temporelles, gros jeux de données, …).

  • read.table() et read.csv() permettent d’importer une grande majorité des jeux de données.
  • read.xlsx() du package xlsx permet d’importer des données issues du logiciel Excel.
  • scan(), readline() et readLines() permettent d’importer des données de manière plus flexible (format des données, options d’import, saisie interactive).
  • data() permet de charger un jeu de données (au format .RData ou .rda) contenu dans un package.
  • Le package foreign (R Core Team 2017), installé automatiquement avec R, contient un ensemble de fonctions pour lire et écrire des données issus de logiciels tels que SPSS, SAS, Stata, …
# charger le jeu de données 'iris'
data(iris)

# obtenir des informations sur ce jeu de données
?iris

# consulter et exécuter l'exemple associé au jeu de données 'iris'
example(iris)
## 
## iris> dni3 <- dimnames(iris3)
## 
## iris> ii <- data.frame(matrix(aperm(iris3, c(1,3,2)), ncol = 4,
## iris+                         dimnames = list(NULL, sub(" L.",".Length",
## iris+                                         sub(" W.",".Width", dni3[[2]])))),
## iris+     Species = gl(3, 50, labels = sub("S", "s", sub("V", "v", dni3[[3]]))))
## 
## iris> all.equal(ii, iris) # TRUE
## [1] TRUE

Exporter et sauver des données

L’export des données peut avoir un intérêt soit dans le cas où les données initialement importées ont été modifiées dans R, soit dans le cas où les données ont été générées/simulées dans R.

  • save() sauvegarde un ensemble d’objets R dans un fichier spécifique, généralement au format RData.
  • write.table enregistre un objet à deux dimensions (de type tableau) dans un fichier.

2.1.2 Les types de données

Ici encore, sont présentés les principaux types de données. Il existe en effet d’autres types de données (dates, séries temporelles, données spatiales, …) et les possibilités de typage sont enrichies par de nouveaux packages.

Les données numériques

  • numeric, double, integer
  • Tester si un objet est numérique : is.numeric(), is.double(), is.integer()
  • Convertir un objet en numérique : as.numeric(), as.double(), as.integer()

Les facteurs

  • factor
  • Tester si un objet un facteur : is.factor()
  • Convertir un objet en facteur : as.factor()
  • Les facteurs sont des variables catégorielles qui possèdent un attribut levels définissant l’ensemble des valeurs que peut prendre le facteur.
  • Lors de l’import de données, il faut rester vigilent sur le typage automatique des données, notamment pour les facteurs. Par exemple, une variable contenant des informations relatives au sexe d’un individu et prenant les valeurs 1 et 2 sera automatiquement définie comme numérique et devra donc être convertie en facteur pour être traitée correctement.

Les caractères

  • character
  • Tester si un objet est un caratère : is.character()
  • Convertir un objet en caractère : as.character()
  • Concaténer deux chaînes de caractères : paste()
  • Chaînes de caractères prédéfinies : letters, LETTERS, month.abb, month.name

Les valeurs booléennes

  • TRUE et FALSE
  • Tester si un objet est booléen : is.logical()
  • Convertir un objet en booléen : as.logical()
  • Grammaire logique : !, &, |
  • Tester si une valeur est égale à TRUE : isTRUE()

Les valeurs manquantes

  • NA (i.e. Not Available) est une valeur logique, de longueur 1, qui contient un indicateur de valeur manquante. La fonction is.na() permet de tester si une valeur est manquante.
  • NaN (i.e. Not a Number) matérialise une valeur numérique qui n’est pas réelle. La fonction is.nan() permet de tester si une valeur est finie ou infinie.
  • NULL (mot réservé) représente un objet vide. La fonction is.null() permet de tester si une valeur est définie. NULL est différent de NA.

2.1.3 Les structures de données

Quelques commandes utiles

  • str() permet de visualiser de manière résumée la structure d’un objet.
  • class() et typeof() renvoient respectivement la classe (au sens POO) et le type d’un objet (au sens type de R). La classe d’un objet peut être définie par l’utilisateur, pas son type. Les deux fonctions peuvent renvoyer le même résultat.
  • names(), colnames() et rownames() renvoient respectivement, s’ils existent, les noms d’un objet, le nom des colonnes et des lignes d’un objet.
  • length() et dim() renvoient respectivement la longueur et la dimension d’un objet.
  • head() et tail() renvoient respectivement les premiers et les derniers éléments d’un objet.
  • [, [[ et $ permettent d’extraire, dans la mesure du possible, un ou plusieurs éléments d’un objet.
  • L’extraction d’un élément d’un objet peut se faire en spécifiant :
    • un entier positif, pour conserver les éléments situés à une position spécifique
    • un entier négatif, pour supprimer les éléments situés à une position spécifique
    • un booléen, pour conserver les éléments pour lesquels la valeur est TRUE
    • une chaîne de caractère, pour conserver les éléments dont le nom correspond
  • A noter : l’indexation des objets commence à 1 (et non à 0, comme dans certains langages).

Les vecteurs

  • Le vecteur est la structure de base des objets dans R.
  • Un vecteur rassemble nécessairement des données de type homogène.
  • Créer un vecteur : vector()
  • Tester si un objet est un vecteur : is.vector()
  • Convertir un objet en vecteur : as.vector()
  • Générer quelques vecteurs utiles : seq(), c(), rep(), :
# créer un vecteur 'v1' de longueur 3
v1 <- vector(mode = "numeric", length = 3)

# afficher 'v1'
v1
## [1] 0 0 0
# tester si 'v1' est bien un objet de classe 'vector'
is.vector(v1)
## [1] TRUE
# connaître la longueur de l'objet 'v1'
length(v1)
## [1] 3
# connaître la dimension de l'objet 'v1'
dim(v1)
## NULL
# créer une séquence régulière entre 1 et 10, d'intervalle 0.5
seq(from = 1, to = 10, by = 0.5)
##  [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5
## [15]  8.0  8.5  9.0  9.5 10.0
# créer une séquence régulière d'entiers entre 0 et 10
0:10
##  [1]  0  1  2  3  4  5  6  7  8  9 10
# créer un vecteur 'v2' qui concatène les caractères 'a', 'b', 'c' et 'd'
v2 <- c("a", "b", "c", "d")

# afficher 'v2'
v2
## [1] "a" "b" "c" "d"
# connaître la classe de l'objet 'v2'
class(v2)
## [1] "character"
# tester si l'objet 'v2' est de classe 'character'
is.character(v2)
## [1] TRUE
# tester si l'objet 'v2' est de classe 'vector'
is.vector(v2)
## [1] TRUE
# extraire l'élément en première position de 'v2'
v2[1]
## [1] "a"
# remplacer le 1er élément de 'v2' par la valeur '2'
v2[1] <- 2

# afficher 'v2'
# noter que la valuer numérique '2' a été convertie en chaîne de caratère pour que l'objet 'v2' reste cohérent
v2
## [1] "2" "b" "c" "d"
# créer un vecteur qui répète la valeur 'TRUE' 10 fois
rep(TRUE, times = 10)
##  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

Les matrices

  • Une matrice rassemble nécessairement des données de type homogène.
  • Créer une matrice : matrix()
  • Tester si un objet est une matrice : is.matrix()
  • Convertir un objet en matrice : as.matrix()
  • Combiner des matrices : cbind(), rbind()
  • Connaître le nombre de lignes et de colonnes d’une matrice : nrow(), ncol()
# créer une matrice 'm1' de 10 lignes et 3 colonnes, contenant des valeurs NA 
m1 <- matrix(NA, nrow = 10, ncol = 3)

# afficher 'm1'
m1
##       [,1] [,2] [,3]
##  [1,]   NA   NA   NA
##  [2,]   NA   NA   NA
##  [3,]   NA   NA   NA
##  [4,]   NA   NA   NA
##  [5,]   NA   NA   NA
##  [6,]   NA   NA   NA
##  [7,]   NA   NA   NA
##  [8,]   NA   NA   NA
##  [9,]   NA   NA   NA
## [10,]   NA   NA   NA
# tester si 'm1' est un objet de classe 'matrix'
is.matrix(m1)
## [1] TRUE
# connaître la dimension de l'objet 'm1'
dim(m1)
## [1] 10  3
# connaître le nombre de lignes dans 'm1'
nrow(m1)
## [1] 10
# connaître le nombre de colonnes dans 'm1'
ncol(m1)
## [1] 3
# créer une matrice 'm2' de même dimension que 'm1', remplie par une séquence régulière d'entiers entre 1 et 30
m2 <- matrix(seq(1, 30), nrow = nrow(m1), ncol = ncol(m1))

# afficher 'm2'
m2
##       [,1] [,2] [,3]
##  [1,]    1   11   21
##  [2,]    2   12   22
##  [3,]    3   13   23
##  [4,]    4   14   24
##  [5,]    5   15   25
##  [6,]    6   16   26
##  [7,]    7   17   27
##  [8,]    8   18   28
##  [9,]    9   19   29
## [10,]   10   20   30
# créer une matrice 'm3' de même dimension que 'm1', remplie par une séquence régulière d'entiers entre 1 et 30, en effectuant le remplissage ligne par ligne et non colonne par colonne
m3 <- matrix(seq(1, 30), nrow = 10, ncol = 3, byrow = TRUE)

# afficher 'm3'
m3
##       [,1] [,2] [,3]
##  [1,]    1    2    3
##  [2,]    4    5    6
##  [3,]    7    8    9
##  [4,]   10   11   12
##  [5,]   13   14   15
##  [6,]   16   17   18
##  [7,]   19   20   21
##  [8,]   22   23   24
##  [9,]   25   26   27
## [10,]   28   29   30
# extraire la première colonne de 'm3'
m3[, 1]
##  [1]  1  4  7 10 13 16 19 22 25 28
# extraire la deuxième ligne de 'm3'
m3[2, ]
## [1] 4 5 6
# extraire l'élément à la 4ème ligne et 3ème colonne de 'm3'
m3[4, 3]
## [1] 12
# extraire l'élément à la 4ème ligne et 4ème colonne de 'm3'
m3[4, 4]
## Error in m3[4, 4]: indice hors limites
# juxtaposer 'm2' et 'm3' en colonne
cbind(m2, m3)
##       [,1] [,2] [,3] [,4] [,5] [,6]
##  [1,]    1   11   21    1    2    3
##  [2,]    2   12   22    4    5    6
##  [3,]    3   13   23    7    8    9
##  [4,]    4   14   24   10   11   12
##  [5,]    5   15   25   13   14   15
##  [6,]    6   16   26   16   17   18
##  [7,]    7   17   27   19   20   21
##  [8,]    8   18   28   22   23   24
##  [9,]    9   19   29   25   26   27
## [10,]   10   20   30   28   29   30
# juxtaposer 'm2' et 'm3' en ligne
rbind(m2, m3)
##       [,1] [,2] [,3]
##  [1,]    1   11   21
##  [2,]    2   12   22
##  [3,]    3   13   23
##  [4,]    4   14   24
##  [5,]    5   15   25
##  [6,]    6   16   26
##  [7,]    7   17   27
##  [8,]    8   18   28
##  [9,]    9   19   29
## [10,]   10   20   30
## [11,]    1    2    3
## [12,]    4    5    6
## [13,]    7    8    9
## [14,]   10   11   12
## [15,]   13   14   15
## [16,]   16   17   18
## [17,]   19   20   21
## [18,]   22   23   24
## [19,]   25   26   27
## [20,]   28   29   30

Les data frames

  • Le data.frame est une structure spécifique à R.
  • Un data frame peut contenir des données de type hétérogène.
  • Un data frame est un tableau à deux dimensions, dans lequel les colonnes peuvent avoir des types différents.
  • Créer un data frame : data.frame()
  • Tester si un objet est un data frame : is.data.frame()
  • Convertir un objet en data frame : as.data.frame()
  • Connaître le nom des lignes et des colonnes d’un data frame : colnames(), rownames()
# tester si 'iris' est un data.frame
is.data.frame(iris)
## [1] TRUE
# connaître la dimension de l'objet 'iris'
dim(iris)
## [1] 150   5
# afficher la structure de l'objet 'iris'
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
# connaître le nom des colonnes de 'iris'
colnames(iris)
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width" 
## [5] "Species"
# connaître le nom des lignes de 'iris'
rownames(iris)
##   [1] "1"   "2"   "3"   "4"   "5"   "6"   "7"   "8"   "9"   "10"  "11" 
##  [12] "12"  "13"  "14"  "15"  "16"  "17"  "18"  "19"  "20"  "21"  "22" 
##  [23] "23"  "24"  "25"  "26"  "27"  "28"  "29"  "30"  "31"  "32"  "33" 
##  [34] "34"  "35"  "36"  "37"  "38"  "39"  "40"  "41"  "42"  "43"  "44" 
##  [45] "45"  "46"  "47"  "48"  "49"  "50"  "51"  "52"  "53"  "54"  "55" 
##  [56] "56"  "57"  "58"  "59"  "60"  "61"  "62"  "63"  "64"  "65"  "66" 
##  [67] "67"  "68"  "69"  "70"  "71"  "72"  "73"  "74"  "75"  "76"  "77" 
##  [78] "78"  "79"  "80"  "81"  "82"  "83"  "84"  "85"  "86"  "87"  "88" 
##  [89] "89"  "90"  "91"  "92"  "93"  "94"  "95"  "96"  "97"  "98"  "99" 
## [100] "100" "101" "102" "103" "104" "105" "106" "107" "108" "109" "110"
## [111] "111" "112" "113" "114" "115" "116" "117" "118" "119" "120" "121"
## [122] "122" "123" "124" "125" "126" "127" "128" "129" "130" "131" "132"
## [133] "133" "134" "135" "136" "137" "138" "139" "140" "141" "142" "143"
## [144] "144" "145" "146" "147" "148" "149" "150"
# afficher les 4 premières lignes de 'iris'
head(iris, n = 4)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
# créer un data frame 'df1' défini par une colonne 'age' et une colonne 'sexe'
df1 <- data.frame("age" = c(12, 15, 23, 43, 18, 38), "sexe" = c("M", "M", "F", "F", "F", "M"))

# affichier 'df1'
df1
##   age sexe
## 1  12    M
## 2  15    M
## 3  23    F
## 4  43    F
## 5  18    F
## 6  38    M
# tester si 'df1' est un objet de classe 'data.frame'
is.data.frame(df1)
## [1] TRUE
# afficher la 1ère colonne de 'df1'
df1[, 1]
## [1] 12 15 23 43 18 38
# afficher la colonne de 'df1' qui se nomme 'age'
df1$age
## [1] 12 15 23 43 18 38

Les listes

  • Une liste peut contenir des données de type et de structure hétérogène.
  • Créer une liste : list()
  • Tester si un objet est une liste : is.list()
  • Convertir un objet en liste : as.list()
  • Simplifier une liste en vecteur : unlist()
# créer une liste 'l1'
l1 <- list(1:3, "a", c(TRUE, FALSE, TRUE), c(2.3, 5.9))

# afficher 'l1'
l1
## [[1]]
## [1] 1 2 3
## 
## [[2]]
## [1] "a"
## 
## [[3]]
## [1]  TRUE FALSE  TRUE
## 
## [[4]]
## [1] 2.3 5.9
# tester si 'l1' est un objet de classe 'list'
is.list(l1)
## [1] TRUE
# afficher la structure de l'objet 'l1'
str(l1)
## List of 4
##  $ : int [1:3] 1 2 3
##  $ : chr "a"
##  $ : logi [1:3] TRUE FALSE TRUE
##  $ : num [1:2] 2.3 5.9
# simplifier 'l1' en vecteur
unlist(l1)
## [1] "1"     "2"     "3"     "a"     "TRUE"  "FALSE" "TRUE"  "2.3"   "5.9"
# afficher le nom des éléments de la liste 'l1'
names(l1)
## NULL
# attribuer des noms aux éléments de la liste 'l1'
names(l1) <- c("int", "chr", "logi", "num")

# afficher le nom des éléments de la liste 'l1'
names(l1)
## [1] "int"  "chr"  "logi" "num"
# afficher la structure de l'objet 'l1'
str(l1)
## List of 4
##  $ int : int [1:3] 1 2 3
##  $ chr : chr "a"
##  $ logi: logi [1:3] TRUE FALSE TRUE
##  $ num : num [1:2] 2.3 5.9
# extraire le 4ème élément de la liste 'l1'
l1[[4]]
## [1] 2.3 5.9
# extraire le 1er élément du 4ème élément de la liste 'l1'
l1[[4]][1]
## [1] 2.3
# extraire l'élément de la liste 'l1' qui se nomme 'int'
l1$int
## [1] 1 2 3

2.2 Eléments de programmation

2.2.1 Les structures de contrôle

Les structures conditionnelles : if, else, ifelse et switch

  • if(test)
  • if(test) expr.oui else expr.non
  • ifelse(test, oui, non). A manipuler avec précaution : les objets en sortie doivent avoir la même taille et la même structure que l’objet en entrée. Cette fonction est donc facilement source d’erreur, en plus d’être réputée assez lente.
  • switch(var, val1 = expr.val1, val2 = expr.val2, val3 = expr.val3, ...)
# calculer la racine carrée d'un nombre 'n' uniquement s'il est supérieur ou égal à 0
n <- 10
if(n >= 0) {
    n_sqrt <- sqrt(n)
} else {
    n_sqrt <- NaN
}
n_sqrt
## [1] 3.162278
# calculer 'n_sqrt' en utilisant la commande 'ifelse'
n_sqrt <- ifelse(n >= 0, sqrt(n), NaN)
n_sqrt
## [1] 3.162278

Les structures itératives : for, while et repeat

  • for(var in seq) expr
  • while(test) expr. L’expression continue à être exécutée tant qu’une condition est respectée.
  • repeat expr
  • break et next permettent respectivement d’interrompre une boucle ou de passer à l’itération suivante.
  • La boucle for incrémente elle-même l’itérateur.
  • Pour while et repeat, il est primordial d’incrémenter explicitement l’itérateur, sans quoi, le code pourrait boucler à l’infini et endommager un programme.
# créer un vecteur 'v3' contenant le carré des entiers de 1 à 10, rempli élément par élément
v3 <- vector()
v3
## logical(0)
for(it in 1:10) {
    v3[it] <- it * it
}
v3
##  [1]   1   4   9  16  25  36  49  64  81 100
# ajouter '1' à chaque élément de 'v3'
it <- 1
while(it <= length(v3)) {
    v3[it] <- v3[it] + 1
    it <- it + 1
}
v3
##  [1]   2   5  10  17  26  37  50  65  82 101
# remplacer les 3 premiers éléments de 'v3' par 'NA'
it <- 1
repeat {
    v3[it] <- NA
    it <- it + 1
    if(it > 3)
        break
}
v3
##  [1]  NA  NA  NA  17  26  37  50  65  82 101

2.2.2 Les fonctions

Utiliser une fonction existante

  • Plusieurs dizaines de fonctions ont déjà été utilisées depuis le début de ce document (install.packages(), library(), read.table(), data(), is.numeric(), as.numeric(), …).
  • ls() liste l’ensemble des objets dans un environnement, donc dans un package.
  • args(), formals() et formalArgs() donnent, sous différentes formes, les éléments qui définissent une fonction, notamment les arguments.
  • Il n’est pas impératif de mentionner le nom des arguments pour utiliser une fonction, à condition qu’il n’y ait pas d’ambiguïté entre les différents paramètres. Cependant, pour une meilleure lisibilité et une meilleure performance, il est recommandé d’expliciter le nom des arguments auxquels des valeurs sont données.
# connaître le nom des arguments de la fonction 'read.table' et leur valeur par défaut
args(read.table)
## function (file, header = FALSE, sep = "", quote = "\"'", dec = ".", 
##     numerals = c("allow.loss", "warn.loss", "no.loss"), row.names, 
##     col.names, as.is = !stringsAsFactors, na.strings = "NA", 
##     colClasses = NA, nrows = -1, skip = 0, check.names = TRUE, 
##     fill = !blank.lines.skip, strip.white = FALSE, blank.lines.skip = TRUE, 
##     comment.char = "#", allowEscapes = FALSE, flush = FALSE, 
##     stringsAsFactors = default.stringsAsFactors(), fileEncoding = "", 
##     encoding = "unknown", text, skipNul = FALSE) 
## NULL
head(formals(read.table))
## $file
## 
## 
## $header
## [1] FALSE
## 
## $sep
## [1] ""
## 
## $quote
## [1] "\"'"
## 
## $dec
## [1] "."
## 
## $numerals
## c("allow.loss", "warn.loss", "no.loss")
formalArgs(read.table)
##  [1] "file"             "header"           "sep"             
##  [4] "quote"            "dec"              "numerals"        
##  [7] "row.names"        "col.names"        "as.is"           
## [10] "na.strings"       "colClasses"       "nrows"           
## [13] "skip"             "check.names"      "fill"            
## [16] "strip.white"      "blank.lines.skip" "comment.char"    
## [19] "allowEscapes"     "flush"            "stringsAsFactors"
## [22] "fileEncoding"     "encoding"         "text"            
## [25] "skipNul"
# afficher les 20 premières fonctions disponibles dans le package 'stats'
head(ls("package:stats"), 20)
##  [1] "acf"                  "acf2AR"               "add.scope"           
##  [4] "add1"                 "addmargins"           "aggregate"           
##  [7] "aggregate.data.frame" "aggregate.ts"         "AIC"                 
## [10] "alias"                "anova"                "ansari.test"         
## [13] "aov"                  "approx"               "approxfun"           
## [16] "ar"                   "ar.burg"              "ar.mle"              
## [19] "ar.ols"               "ar.yw"

Créer sa propre fonction

  • Il est bien sûr possible de créer sa propre fonction.
  • Une valeur par défaut peut être prise par un ou tous les arguments d’une fonction. Déterminer des valeurs par défaut peut faciliter l’usage d’une fonction.
  • Par construction, il n’y a pas de contrôle sur le typage des objets. Introduire des contrôles dans le corps de sa fonction est un bon réflexe pour se prémunir d’erreurs typiques et pour orienter l’utilisateur.
  • return() permet de matérialiser les éléments renvoyés par la fonction créée.
  • invisible() permet de retourner une copie (temporairement) invisible d’un objet.
  • on.exit() permet de stocker des valeurs d’éléments qui seront restaurées à la fin/sortie de la fonction.
  • stop(), stopifnot(), message() et error() permettent de caractériser les messages envoyés à l’utilisateur au cours de l’exécution d’une fonction.
  • Plus l’indentation du corps de la fonction sera soignée, plus la fonction sera lisible, compréhensible, donc facilement utilisée.
# créer une fonction 'maFctnCarre' qui calcule le carré d'un entier
maFctnCarre <- function(n) {
    return(n * n)
}

# appliquer la fonction 'maFctnCarre' avec 'n = 3'
maFctnCarre(n = 3)
## [1] 9
# améliorer la fonction 'maFctnCarre' de façon à ce que l'argument 'n' prenne la valeur '0' par défaut
maFctnCarre <- function(n = 0) {
    return(n * n)
}

# appliquer la fonction 'maFctnCarre' sans valeur au paramètre
maFctnCarre()
## [1] 0
# appliquer la fonction 'maFctnCarre' à un objet non numérique
maFctnCarre(n = "n")
## Error in n * n: argument non numérique pour un opérateur binaire
maFctnCarre(n = NA)
## [1] NA
# améliorer la fonction 'maFctnCarre' de façon à ce qu'elle s'interrompe si 'n' n'est pas numérique
maFctnCarre <- function(n = 0) {
    if(!is.numeric(n))
        stop("'n' doit être une valeur numérique")
    return(n * n)
}

# appliquer la fonction 'maFctnCarre' à un objet non numérique
maFctnCarre(n = "n")
## Error in maFctnCarre(n = "n"): 'n' doit être une valeur numérique
maFctnCarre(n = NA)
## Error in maFctnCarre(n = NA): 'n' doit être une valeur numérique

2.2.3 Les sytèmes orientés objet

Différents systèmes orientés objet (OO) coexistent dans R : S3, S4, RC (Reference Classes) et les types de base (qui ne sont pas vraiment un système objet puisque seuls les membres de la R Core Team peuvent créer de nouveaux types).

S3

  • le premier et le plus simple système OO dans R
  • le seul système OO utilisé dans les packages base (R Core Team 2018a) et stats (R Core Team 2018a)
  • le plus couramment utilisé dans les packages disponibles sur CRAN
  • système assez léger, souple, flexible
  • en contrepartie, la protection des objets n’est pas garantie

  • basé sur le concept des fonctions génériques
  • pas de définition formelle des classes
  • pas de manière simple de tester si un objet est de type S3 : is.object(x) & !isS4(x)
  • méthodes reconnaissables grâce à leur syntaxe du type generic.class() où le nom de la fonction générique et le nom de la classe d’objet sont séparés par un point3

  • En pratique, un objet peut être déclaré comme une instance d’une classe au moment de sa création ou a posteriori.
# créer un objet 'lionel' de classe 'personne'
lionel <- structure(list("nom" = "Lionel", "age" = 38), class = "personne")
lionel
## $nom
## [1] "Lionel"
## 
## $age
## [1] 38
## 
## attr(,"class")
## [1] "personne"
class(lionel)
## [1] "personne"
# créer une liste 'paul'
paul <- list("nom" = "Paul", "age" = 32)
paul
## $nom
## [1] "Paul"
## 
## $age
## [1] 32
class(paul)
## [1] "list"
# attribuer à l'objet 'paul' la classe 'personne'
class(paul) <- "personne"
paul
## $nom
## [1] "Paul"
## 
## $age
## [1] 32
## 
## attr(,"class")
## [1] "personne"
class(paul)
## [1] "personne"
inherits(paul, "personne")
## [1] TRUE
is.object(paul) & !isS4(paul)
## [1] TRUE
  • Pour créer une nouvelle fonction générique, il faut définir une fonction qui appelle UseMethod().
  • Une fonction générique n’est utile que si elle possède des méthodes.
  • Pour créer une méthode, il faut définir une fonction régulière dont le nom a la syntaxe approprié.
  • Le signe $ permet d’accèder aux attributs d’un objet.
travailler <- function(x) UseMethod("travailler")
travailler.personne <- function(x) "Développer des codes informatiques"
travailler(lionel)
## [1] "Développer des codes informatiques"
summary.personne <- function(x) paste(x$nom, "a", x$age, "ans.")
summary(lionel)
## [1] "Lionel a 38 ans."
summary(paul)
## [1] "Paul a 32 ans."
  • methods() permet d’afficher toutes les méthodes qui appartiennent à une fonction générique ou relatives à une classe.
  • getS3method() permet d’afficher une méthode pour une classe particulière.
summary
## function (object, ...) 
## UseMethod("summary")
## <bytecode: 0x5f31c60>
## <environment: namespace:base>
methods("summary")
##  [1] summary.4thcorner*             summary.aov                   
##  [3] summary.aovlist*               summary.aspell*               
##  [5] summary.between*               summary.betwit*               
##  [7] summary.check_packages_in_dir* summary.coinertia*            
##  [9] summary.connection             summary.corkdist*             
## [11] summary.data.frame             summary.Date                  
## [13] summary.default                summary.dist*                 
## [15] summary.dpcoa*                 summary.dudi*                 
## [17] summary.ecdf*                  summary.factor                
## [19] summary.glm                    summary.inertia*              
## [21] summary.infl*                  summary.lm                    
## [23] summary.loess*                 summary.loglm*                
## [25] summary.manova                 summary.matrix                
## [27] summary.mcoa*                  summary.mfa*                  
## [29] summary.mlm*                   summary.multiblock*           
## [31] summary.multispati*            summary.negbin*               
## [33] summary.neig*                  summary.nls*                  
## [35] summary.orthobasis*            summary.packageStatus*        
## [37] summary.pcaiv*                 summary.pcaivortho*           
## [39] summary.PDF_Dictionary*        summary.PDF_Stream*           
## [41] summary.personne               summary.polr*                 
## [43] summary.POSIXct                summary.POSIXlt               
## [45] summary.ppr*                   summary.prcomp*               
## [47] summary.princomp*              summary.proc_time             
## [49] summary.rlm*                   summary.rlq*                  
## [51] summary.sepan*                 summary.srcfile               
## [53] summary.srcref                 summary.stepfun               
## [55] summary.stl*                   summary.table                 
## [57] summary.tukeysmooth*           summary.within*               
## [59] summary.witwit*               
## see '?methods' for accessing help and source code
exists("summary.default")
## [1] TRUE
exists("summary.personne")
## [1] TRUE
getS3method("summary", "default")
## function (object, ..., digits) 
## {
##     if (is.factor(object)) 
##         return(summary.factor(object, ...))
##     else if (is.matrix(object)) {
##         if (missing(digits)) 
##             return(summary.matrix(object, ...))
##         else return(summary.matrix(object, digits = digits, ...))
##     }
##     value <- if (is.logical(object)) 
##         c(Mode = "logical", {
##             tb <- table(object, exclude = NULL, useNA = "ifany")
##             if (!is.null(n <- dimnames(tb)[[1L]]) && any(iN <- is.na(n))) dimnames(tb)[[1L]][iN] <- "NA's"
##             tb
##         })
##     else if (is.numeric(object)) {
##         nas <- is.na(object)
##         object <- object[!nas]
##         qq <- stats::quantile(object)
##         qq <- c(qq[1L:3L], mean(object), qq[4L:5L])
##         if (!missing(digits)) 
##             qq <- signif(qq, digits)
##         names(qq) <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", 
##             "Max.")
##         if (any(nas)) 
##             c(qq, `NA's` = sum(nas))
##         else qq
##     }
##     else if (is.recursive(object) && !is.language(object) && 
##         (n <- length(object))) {
##         sumry <- array("", c(n, 3L), list(names(object), c("Length", 
##             "Class", "Mode")))
##         ll <- numeric(n)
##         for (i in 1L:n) {
##             ii <- object[[i]]
##             ll[i] <- length(ii)
##             cls <- oldClass(ii)
##             sumry[i, 2L] <- if (length(cls)) 
##                 cls[1L]
##             else "-none-"
##             sumry[i, 3L] <- mode(ii)
##         }
##         sumry[, 1L] <- format(as.integer(ll))
##         sumry
##     }
##     else c(Length = length(object), Class = class(object), Mode = mode(object))
##     class(value) <- c("summaryDefault", "table")
##     value
## }
## <bytecode: 0x5008008>
## <environment: namespace:base>
getS3method("summary", "personne")
## function(x) paste(x$nom, "a", x$age, "ans.")
## <bytecode: 0x5466f00>
methods(class = "personne")
## [1] summary    travailler
## see '?methods' for accessing help and source code

S4

  • plus formel, plus rigoureux, plus verbeux que le S3
  • permet l’héritage multiple et la correspondance multiple
  • pas de S4 dans les packages de base de R
  • le package methods (inclus dans l’installation de base de R) contient tout le code relatif à la mise en place du S4 dans R
  • très développé dans Bioconductor, du fait de la complexité des données

  • new() crée un nouvel objet d’une classe.
  • S’il existe, il est préférable d’utiliser le constructeur de classe (qui a généralement le même nom que la classe) plutôt que new() pour créer un nouvel objet.
  • Les classes S4 peuvent être protégées grâce à la définition
    • de l’argument validity (définit au même moment que la classe) ou de la méthode validity() (appelée a posteriori de la définition de la classe) qui s’assurent qu’un objet respecte bien les conditions de validité définies pour sa classe
    • d’un objet prototype qui précise les valeurs par défaut d’un ou plusieurs attributs de la classe.
  • isS4() teste si un objet est de type S4.
  • Le signe @ et la fonction slot() accèdent aux attributs d’un objet.
  • methods(class = "") liste aussi bien les méthodes S3 que S4. Pour les lister séparemment, utiliser les commandes .S3methods(class = "") et .S4methods(class = "").
  • setGeneric() crée une nouvelle fonction générique ou convertit une fonction déjà existante en générique.
  • setMethod() prend en paramètre le nom d’une fonction générique, les classes qui sont associées à cette générique et une fonction qui implémente la méthode.
  • callNextMethod() permet d’appeler la méthode de la classe parente.

# créer une classe 'Personne' définie par 3 attributs
setClass("Personne",
  representation = list(nom = "character", age = "numeric", fonction = "character")
)

# créer une classe 'Stagiaire' qui hérite de la classe 'Personne' et qui a un attribut supplémentaire
setClass("Stagiaire",
  representation = list(tuteur = "Personne"),
  contains = "Personne")

# créer un objet de la classe 'Personne' et un objet de la classe 'Stagiaire'
vincent <- new("Personne", nom = "Vincent", age = 33, fonction = "Ingénieur")
florent <- new("Stagiaire", nom = "Florent", age = 22, fonction = "Etudiant", tuteur = vincent)

# afficher l'attribut 'fonction' de l'objet 'vincent'
vincent@fonction
## [1] "Ingénieur"
# afficher l'attribut 'age' de l'objet 'florent'
slot(florent, "age")
## [1] 22
# tester si 'florent' est un objet S4
isS4(florent)
## [1] TRUE
# afficher la fonction générique 'interagir' 
setGeneric("interagir")
## Error in setGeneric("interagir"): must supply a function skeleton for 'interagir', explicitly or via an existing function
# créer la fonction générique 'interagir' vu qu'elle n'existe pas
setGeneric("interagir", function(x, y) {
  standardGeneric("interagir")
})
## [1] "interagir"
# définir une nouvelle méthode 'interagir' qui prend en paramètre deux objets de la classe 'Personne'
setMethod("interagir",
  c(x = "Personne", y = "Personne"),
  function(x, y) {
    "Boire le café ensemble."
  }
)
## [1] "interagir"
# appliquer la méthode 'interagir' aux objets 'vincent' et 'florent'
interagir(vincent, florent)
## [1] "Boire le café ensemble."
# définir une nouvelle méthode 'interagir' qui prend en paramètre un objet de la classe 'Personne' et un objet de la classe 'Stagiaire'
setMethod("interagir",
  c(x = "Personne", y = "Stagiaire"),
  function(x, y) {
    paste("Faire le point sur le stage en cours.", 
          callNextMethod())
  }
)
## [1] "interagir"
# appliquer la méthode 'interagir' aux objets 'vincent' et 'florent'
interagir(vincent, florent)
## [1] "Faire le point sur le stage en cours. Boire le café ensemble."
# créer un objet de la classe 'Personne' 
stéphane <- new("Personne", nom = "Stéphane", age = -36, fonction = "Assistant Ingénieur")

# afficher l'attribut 'age' de l'objet 'stéphane'
stéphane@age
## [1] -36
# réécrire la classe 'Personne' en définissant une condition sur l'attribut 'age'
setClass("Personne",
  representation = list(nom = "character", age = "numeric", fonction = "character"),
  validity = function(object){
      if(object@age < 0)
          stop("L'âge de ", object@nom, " ne peut pas être négatif.")
  }
)

# créer un objet de la classe 'Personne' 
stéphane <- new("Personne", nom = "Stéphane", age = -36, fonction = "Assistant Ingénieur")
## Error in validityMethod(object): L'âge de Stéphane ne peut pas être négatif.
stéphane <- new("Personne", nom = "Stéphane", age = 36, fonction = "Assistant Ingénieur")

# appliquer la méthode 'interagir' aux objets 'vincent' et 'florent'
interagir(vincent, stéphane)
## [1] "Boire le café ensemble."
# afficher les méthodes de la classe 'Personne'
methods(class = "Personne")
## [1] interagir
## see '?methods' for accessing help and source code
.S3methods(class = "Personne")
## no methods found
.S4methods(class = "Personne")
## [1] interagir
## see '?methods' for accessing help and source code

3 L’essentiel pour mener une étude statistique dans R

L’analyse statistique des données est au cœur du projet R. Pour cette raison historique, toujours plus de packages mettent à disposition de l’utilisateur de nouvelles méthodes pour manipuler les données, de nouvelles méthodes d’analyse, de nouvelles méthodes de représentation graphique.

3.1 Manipuler les données

Transformer les données :

  • pour nettoyer les données brutes qui viennent d’être importées
  • plutôt depuis une session R que directement dans le fichier des données brutes
  • en gardant une trace des étapes de transformation dans un script R pour pouvoir les reproduire éventuellement
  • pour rendre les données exploitables au sens d’une analyse statistique
  • trier, sélectionner, couper, jointer, …

3.1.1 Quelques ustensiles pour le ménage et le rangement

  • sort() , order() et rank() pour trier et ordonner un vecteur
v4 <- c(1, 1, 3:1, 1:4, 3)
v4
##  [1] 1 1 3 2 1 1 2 3 4 3
sort(v4)
##  [1] 1 1 1 1 2 2 3 3 3 4
order(v4)
##  [1]  1  2  5  6  4  7  3  8 10  9
v4[order(v4)]
##  [1] 1 1 1 1 2 2 3 3 3 4
rank(v4)
##  [1]  2.5  2.5  8.0  5.5  2.5  2.5  5.5  8.0 10.0  8.0
v5 <- c("r", "a", "g")
v5
## [1] "r" "a" "g"
sort(v5)
## [1] "a" "g" "r"
order(v5)
## [1] 2 3 1
v5[order(v5)]
## [1] "a" "g" "r"
rank(v5)
## [1] 3 1 2
  • sample() pour échantillonner un nombre fini d’éléments, avec ou sans remise
# sélectionner au hasard 10 individus dans le jeu de données 'iris'
iris[sample(1:nrow(iris), 10), ]
##     Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 24           5.1         3.3          1.7         0.5     setosa
## 107          4.9         2.5          4.5         1.7  virginica
## 110          7.2         3.6          6.1         2.5  virginica
## 94           5.0         2.3          3.3         1.0 versicolor
## 45           5.1         3.8          1.9         0.4     setosa
## 121          6.9         3.2          5.7         2.3  virginica
## 70           5.6         2.5          3.9         1.1 versicolor
## 91           5.5         2.6          4.4         1.2 versicolor
## 122          5.6         2.8          4.9         2.0  virginica
## 132          7.9         3.8          6.4         2.0  virginica
  • table() pour construire une table de contingence
# connaître les valeurs possiblement prises par la colonne 'Species' dans 'iris'
levels(iris$Species)
## [1] "setosa"     "versicolor" "virginica"
# connaître le nombre d'individus dans chacun des niveaux de 'Species'
table(iris$Species)
## 
##     setosa versicolor  virginica 
##         50         50         50
  • which() pour obtenir les positions des éléments qui vérifient la condition précisée
# récupérer les indices des individus pour lesquels 'Species' vaut 'versicolor'
indice_versicolor <- which(iris$Species == "versicolor")
head(indice_versicolor)
## [1] 51 52 53 54 55 56
length(indice_versicolor)
## [1] 50
# sélectionner les individus de l'espèce 'versicolor'
df2 <- iris[indice_versicolor, ]
dim(df2)
## [1] 50  5
  • na.omit() pour supprimer les valeurs NA d’un objet
df3 <- data.frame(x = c(1, 2, 3), y = c(0, 10, NA))
df3
##   x  y
## 1 1  0
## 2 2 10
## 3 3 NA
na.omit(df3)
##   x  y
## 1 1  0
## 2 2 10
  • D’autres fonctions utiles :
    • subset() pour sélectionner un sous-ensemble de données
    • %in% et match() pour obtenir les positions des éléments d’un premier objet qui correspondent avec un deuxième
    • cut() pour couper un vecteur en plusieurs sections et le convertir en facteur
    • with() pour évaluer une expression dans un environnement de données
    • na.fail(), na.exclude(), na.pass() pour traiter les NA

3.1.2 Des spécialistes de la grammaire des données

Le package plyr (Wickham 2011)

  • les fonctions principales : arrange(), mutate(), summarise(), join()
library(plyr)

# trier les données 'iris' dans l'ordre croissant des colonnes 'Sepal.Length' puis 'Sepal.Width'
df4 <- arrange(iris, Sepal.Length, Sepal.Width)
head(df4)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          4.3         3.0          1.1         0.1  setosa
## 2          4.4         2.9          1.4         0.2  setosa
## 3          4.4         3.0          1.3         0.2  setosa
## 4          4.4         3.2          1.3         0.2  setosa
## 5          4.5         2.3          1.3         0.3  setosa
## 6          4.6         3.1          1.5         0.2  setosa
df5 <- mutate(iris, SepalDim = Sepal.Length * Sepal.Width, PetalDim = Petal.Length * Petal.Width)
head(df5)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species SepalDim
## 1          5.1         3.5          1.4         0.2  setosa    17.85
## 2          4.9         3.0          1.4         0.2  setosa    14.70
## 3          4.7         3.2          1.3         0.2  setosa    15.04
## 4          4.6         3.1          1.5         0.2  setosa    14.26
## 5          5.0         3.6          1.4         0.2  setosa    18.00
## 6          5.4         3.9          1.7         0.4  setosa    21.06
##   PetalDim
## 1     0.28
## 2     0.28
## 3     0.26
## 4     0.30
## 5     0.28
## 6     0.68

Le package dplyr (Wickham et al. 2017)

  • les fonctions principales : filter(), arrange(), select(), rename(), mutate(), transmute(), summarise()
  • manipule des tibble, un nouveau format pour stoker les données, adapté notamment pour les gros jeux de données. Les tibbles sont une version optimisée des data frame, dans la mesure où l’affichage se restreint au premières lignes de l’objet.

Et d’autres

  • stringr (Wickham 2018b)
  • tidyr (Wickham and Henry 2018)
  • magrittr (Bache and Wickham 2014)
  • stringi (Gagolewski 2017)

3.2 Analyser les données

Installés avec R, les packages base (R Core Team 2018a) et stats (R Core Team 2018a) contiennent de nombreux outils pour mener une analyse statistique. Par ailleurs, grâce aux nombreux nouveaux packages diffusés sur CRAN, les outils statistiques disponibles sur R se développent pour répondre à de plus en plus de problématiques et à des objectifs de plus en plus précis.

Fonctions utiles dans le cadre d’une analyse

  • print() : pour afficher un résumé succint de l’analyse
  • summary() : pour afficher un résumé détaillé de l’analyse
  • set.seed() : pour fixer le générateur de nombres pseudo-aléatoires. La reproductibilité de résultats liés à des tirages aléatoires est ainsi possible.

3.2.1 Statistiques descriptives

Fonctions mathématiques courantes

  • sum(), cumsum() : somme, somme cumulée
  • prod(), cumprod() : produit, produit cummulé
  • min(), max() : valeurs minimales et maximales
  • log(), exp() : logarithme et exponentielle
  • sqrt() : racine carrée

Fonctions de statistiques descriptives

  • mean() : moyenne
  • mediane() : médiane
  • quantile() : quantiles
  • var() : variance
  • sd() : écart-type
  • cor() : corrélation
  • cov() : covariance

3.2.2 Le calcul matriciel

Appliqués à des vecteurs ou des matrices, les opérateurs mathématiques classiques (+, -, *, /) effectuent les opérations terme à terme.

# créer une matrice 'm4' ayant 3 colonnes, contenant 12 entiers entre 1 et 100
m4 <- matrix(sample(100, 12), ncol = 3)
m4
##      [,1] [,2] [,3]
## [1,]   63   83    6
## [2,]    2   79    7
## [3,]   62   40    4
## [4,]   81   12   59
# créer une matrice 'm5' ayant 3 colonnes, contenant 12 entiers entre 1 et 100
m5 <- matrix(sample(100, 12), ncol = 3)
m5
##      [,1] [,2] [,3]
## [1,]   97   87   19
## [2,]   43    1   61
## [3,]   80    2   85
## [4,]   18   28   15
# mutiplier terme à terme les matrices 'm4' et 'm5'
m4 * m5
##      [,1] [,2] [,3]
## [1,] 6111 7221  114
## [2,]   86   79  427
## [3,] 4960   80  340
## [4,] 1458  336  885

Un ensemble de fonctions sont disponibles pour effectuer des opérations algébriques sur les matrices :

  • t() : transposée de matrice
  • %*% : multiplication matricielle
  • diag() : pour renvoyer la diagonale d’une matrice ou pour créer un matrice diagonale
  • det() et determinant() : déterminant de matrice
  • solve() et ginv() (du package MASS) : pour inverser une matrice (dans le package MASS)
  • eigen(x) pour décomposer en éléments propres une matrice
# transposer la matrice 'm4'
t(m4)
##      [,1] [,2] [,3] [,4]
## [1,]   63    2   62   81
## [2,]   83   79   40   12
## [3,]    6    7    4   59
# effectuer le produit matriciel entre 'm4' et 'm5'
m6 <- t(m4) %*% m5
m6
##       [,1] [,2] [,3]
## [1,] 12615 7875 7804
## [2,] 14864 7716 9976
## [3,]  2265 2189 1766
# afficher les valeurs sur la diagonale de la matrice 'm6'
diag(m6)
## [1] 12615  7716  1766
# créer une matrice carré de taille 3 ayant la valeur '10' sur la diagonale
diag(10, 3)
##      [,1] [,2] [,3]
## [1,]   10    0    0
## [2,]    0   10    0
## [3,]    0    0   10
# inverser la matrice 'm6'
solve(m6)
##               [,1]          [,2]          [,3]
## [1,]  0.0005538254 -0.0002141986 -0.0012373771
## [2,]  0.0002464716 -0.0003104030  0.0006642785
## [3,] -0.0010158216  0.0006594745  0.0013298718
# décomposer en éléments propres la matrice 'm6'
m6ep <- eigen(m6)
m6ep$values
## [1] 23079.8179 -1431.5481   448.7302
m6ep$vectors
##            [,1]       [,2]       [,3]
## [1,] -0.6620027  0.2594414 -0.5998907
## [2,] -0.7351726 -0.8726863  0.1475082
## [3,] -0.1458551  0.4136530  0.7863666

Ces fonctions du package base (R Core Team 2018a) s’avèrent souvent coûteuses, en temps et en mémoire, dès que la dimension des matrices est élevée.

D’autres packages se sont spécialisés dans le traitement, la manipulation et l’analyse des matrices : Matrix (Bates and Maechler 2017), matlib (Friendly and Fox 2016), SparseM (Koenker and Ng 2017)

3.2.3 Les lois de probabilité

Dans le package stats (R Core Team 2018a), de nombreuses distributions de probabilité sont disponibles :

  • beta : beta
  • binom : binomiale
  • cauchy : Cauchy
  • chisq : Chi-deux
  • exp : exponentielle
  • F : F de Fisher
  • gamma : gamma
  • geom : géométrique
  • hyper : hypergéométrique
  • lnorm : log-normale
  • logis : logistique
  • nbinom : binomiale négative
  • norm : normale
  • pois : Poisson
  • signrank : statistique des rangs signés de Wilcoxon
  • t : t de Student
  • unif : uniforme
  • weibull : Weibull
  • wilcox : somme des rangs de Wilcoxon

Quatre fonctions sont associées à chaque distribution. Elles sont appelées en précédant la nom de la distribution par le suffixe approprié :

  • le suffixe d pour obtenir la densité de probabilité
  • le suffixe p pour obtenir la fonction de distribution
  • le suffixe q pour obtenir la fonction des quantiles
  • le suffixe r pour générer aléatoirement des nombres appartenant à la distribution
par(mfrow = c(2, 2))
curve(dnorm, -3, 3, xlab = "z", ylab = "Probability density", main = "Density (dnorm)")
curve(pnorm, -3, 3, xlab = "z", ylab = "Probability", main = "Probability (pnorm)")
curve(qnorm, 0, 1, xlab = "p", ylab = "Quantile (z)", main = "Quantiles (qnorm)")
hist(rnorm(1000), xlab = "z", ylab = "frequency", main = "Random numbers (rnorm)")

Les fonctions graphiques qqnorm(), qqline() et qqplot() sont également disponibles dans le package stats (R Core Team 2018a) pour visualiser les diagrammes quantile-quantile.

y <- rt(200, df = 5)
# qqnorm renvoie le QQplot (plot des quantiles-quantiles) normal pour un jeu de données
qqnorm(y)
# qqline ajoute une ligne
qqline(y, col = 2)

# qqplot renvoie le QQplot de deux jeux de données
qqplot(y, rt(300, df = 5))

3.2.4 Les tests statistiques

  • Comprendre et réaliser les tests statistiques à l’aide de R (Millot 2018)

Egalement dans le package stats (R Core Team 2018a), un grand nombre de fonctions permettent de réaliser les tests statistiques appropriés aux données à analyser :

  • shapiro.test() : Test de la normalité des données
  • bartlett.test() : Test de Bartlett d’homogénéité de variances
  • binom.test() : Test Binomial exact
  • chisq.test() : Test du Chi2
  • cor.test() : Test de corrélation de Pearson, de Kendall ou de Spearman
  • fisher.test() : Test exact de Fisher pour données de comptage
  • t.test() : t-Test de Student de comparaison de moyennes
  • var.test() : Test F de Fisher de comparaison de variances
  • wilcox.test() : Test de rang de Wilcoxon
  • ks.test() : Test de Kolmogorov-Smirnov
# tester l'hypothèse H0 de normalité de 'iris$Sepal.Width'
tn1 <- shapiro.test(iris$Sepal.Width)
tn1
## 
##  Shapiro-Wilk normality test
## 
## data:  iris$Sepal.Width
## W = 0.98492, p-value = 0.1012
tn1$p.value < 0.05
## [1] FALSE
# la p-value n'est pas < 5%. On ne peut pas rejeter l'hypothèse H0.

# représenter l'histogramme des valeurs de 'iris$Sepal.Width'
hist(iris$Sepal.Width)

# tester l'hypothèse H0 de normalité de 'iris$Petal.Width'
tn2 <- shapiro.test(iris$Petal.Width)
tn2
## 
##  Shapiro-Wilk normality test
## 
## data:  iris$Petal.Width
## W = 0.90183, p-value = 1.68e-08
tn2$p.value < 0.05
## [1] TRUE
# la p-value est < à 5%. On rejette l'hypothèse H0.

# représenter l'histogramme des valeurs de 'iris$Petal.Width'
hist(iris$Petal.Width)

# tester l'hypothèse H0 selon laquelle 'iris$Sepal.Length' et 'iris$Petal.Length' ne sont pas corrélées
tc1 <- cor.test(iris$Sepal.Length, iris$Petal.Length)
tc1
## 
##  Pearson's product-moment correlation
## 
## data:  iris$Sepal.Length and iris$Petal.Length
## t = 21.646, df = 148, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8270363 0.9055080
## sample estimates:
##       cor 
## 0.8717538
tc1$estimate
##       cor 
## 0.8717538
tc1$p.value < 0.05
## [1] TRUE
# la p-value est < à 5%. On rejette l'hypothèse H0. 

# représenter 'iris$Sepal.Length' et 'iris$Petal.Length' sur un graphique à deux dimensions
plot(iris$Sepal.Length, iris$Petal.Length)

3.2.5 Analyses exploratoires de données

stats (R Core Team 2018a) contient également des fonctions pour mener des analyses exploratoires sur les données :

  • hclust() : classification hiérarchique
  • kmeans() : classification par la méthode des k-means
  • dist() : calcul de matrices de distance
  • prcomp() : analyse des composantes principales

Cependant, des packages spécialisés pour traiter ces questions sont plus complets et proposent un grand nombre de méthodes d’analyses :

  • les packages de la famille ade4 (Dray and Dufour 2007) : adegraphics(Siberchicot et al. 2017), adegenet(Jombart and Ahmed 2011, Jombart (2008)), adespatial(Dray et al. 2018), adehabitat(Calenge 2006), adephylo(Jombart and Dray 2010), ade4TkGUI(Thioulouse and Dray 2007)
  • FactoMineR (Lê, Josse, and Husson 2008) et SensoMineR (Husson, Le, and Cadoret 2017)
  • cluster (Maechler et al. 2017) : partitionnement des données
  • arm (Gelman and Su 2016) : régression and modèles multi-niveaux et hiérarchiques
data("olympic", package = "ade4")
str(olympic)
## List of 2
##  $ tab  :'data.frame':   33 obs. of  10 variables:
##   ..$ 100 : num [1:33] 11.2 10.9 11.2 10.6 11 ...
##   ..$ long: num [1:33] 7.43 7.45 7.44 7.38 7.43 7.72 7.05 6.95 7.12 7.28 ...
##   ..$ poid: num [1:33] 15.5 15 14.2 15 12.9 ...
##   ..$ haut: num [1:33] 2.27 1.97 1.97 2.03 1.97 2.12 2.06 2 2.03 1.97 ...
##   ..$ 400 : num [1:33] 48.9 47.7 48.3 49.1 47.4 ...
##   ..$ 110 : num [1:33] 15.1 14.5 14.8 14.7 14.4 ...
##   ..$ disq: num [1:33] 49.3 44.4 43.7 44.8 41.2 ...
##   ..$ perc: num [1:33] 4.7 5.1 5.2 4.9 5.2 4.9 5.7 4.8 4.9 5.2 ...
##   ..$ jave: num [1:33] 61.3 61.8 64.2 64 57.5 ...
##   ..$ 1500: num [1:33] 269 273 263 285 257 ...
##  $ score: num [1:33] 8488 8399 8328 8306 8286 ...
# réaliser une ACP centrée réduite sur les données 'olympic'
pca1 <- dudi.pca(olympic$tab, scannf = FALSE)
pca1
## Duality diagramm
## class: pca dudi
## $call: dudi.pca(df = olympic$tab, scannf = FALSE)
## 
## $nf: 2 axis-components saved
## $rank: 10
## eigen values: 3.418 2.606 0.9433 0.878 0.5566 ...
##   vector length mode    content       
## 1 $cw    10     numeric column weights
## 2 $lw    33     numeric row weights   
## 3 $eig   10     numeric eigen values  
## 
##   data.frame nrow ncol content             
## 1 $tab       33   10   modified array      
## 2 $li        33   2    row coordinates     
## 3 $l1        33   2    row normed scores   
## 4 $co        10   2    column coordinates  
## 5 $c1        10   2    column normed scores
## other elements: cent norm
par(mfrow = c(1, 2))
# afficher le cercle des corrélations des variables
s.corcircle(pca1$co)

# afficher les coordonnées des variables et celles des individus dans 'acp1'
scatter(pca1)

3.2.6 La modélisation statistique

La plupart des fonctions issues de packages pour l’ajustement et l’analyse de modèles prennent en entrée un objet formula du type variable à expliquer ~ variables explicatives (voir ?formula) .

Etudier les sorties d’un modèle

  • df.residual() : retourne le nombre de degrés de libertés du résidu
  • coef() : retourne les coefficients estimés
  • residuals() : retourne les résidus
  • fitted() : retourne les valeurs ajustées par le modèle
  • logLik() : calcule la vraisemblance et le nombre de paramètres d’un modèle
  • AIC() : calcule le critère d’information d’Akaike
  • anova() : table d’analyse de la variance

Ajuster un modèle

  • aov() : ajustement d’une analyse de variance
  • lm() : ajustement d’un modèle linéaire
  • glm() : ajustement d’un modèle linéaire généralisé
  • step() : sélection de modèle, pas-à-pas, basé sur le critère de l’AIC

Packages dédiés

  • nlme (Pinheiro et al. 2018) : fonctions pour l’ajustement et la comparaison de modèles linéaires et non-linéaires à effets mixtes
  • lme4 (Bates et al. 2015) : fonctions pour l’ajustement et l’analyse de modèles mixtes linéaires, linéaires généralisés et non linéaires
  • glmnet (Friedman, Hastie, and Tibshirani 2010, Simon et al. (2011)) : fonctions pour modèles Lasso et Elastic-Net
  • fitdistrplus (Delignette-Muller and Dutang 2015) : fonctions pour ajuster des distributions paramétriques à des données censurées et non-censurées
  • rjags (Plummer 2016) : interface avec le logiciel JAGS (JAGS pour Just Another Gibbs Sampler) pour la construction et l’analyse de modèles bayesiens à partir de simulation MCMC (Markov Chain Monte Carlo)
# construire un modèle linéaire
model1 <- as.formula(Sepal.Width ~ Petal.Width + log(Petal.Length) + Species)
lmmodel1 <- lm(formula = model1, 
               data = iris, 
               subset = Sepal.Length > 4.6)

print(lmmodel1)
## 
## Call:
## lm(formula = model1, data = iris, subset = Sepal.Length > 4.6)
## 
## Coefficients:
##       (Intercept)        Petal.Width  log(Petal.Length)  
##            3.1531             0.6620             0.4612  
## Speciesversicolor   Speciesvirginica  
##           -1.9265            -2.3088
summary(lmmodel1)
## 
## Call:
## lm(formula = model1, data = iris, subset = Sepal.Length > 4.6)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.71339 -0.16347  0.01515  0.16655  0.79505 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         3.1531     0.1007  31.298  < 2e-16 ***
## Petal.Width         0.6620     0.1281   5.168 8.27e-07 ***
## log(Petal.Length)   0.4612     0.2541   1.815   0.0717 .  
## Speciesversicolor  -1.9265     0.2423  -7.951 6.37e-13 ***
## Speciesvirginica   -2.3088     0.3087  -7.478 8.37e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2801 on 136 degrees of freedom
## Multiple R-squared:  0.6084, Adjusted R-squared:  0.5969 
## F-statistic: 52.82 on 4 and 136 DF,  p-value: < 2.2e-16
coef(lmmodel1)
##       (Intercept)       Petal.Width log(Petal.Length) Speciesversicolor 
##         3.1531391         0.6620343         0.4611898        -1.9264612 
##  Speciesvirginica 
##        -2.3087904
# construire un modèle avec effets fixes et aléatoires
model2 <- as.formula(Sepal.Width ~ Petal.Width | Species)

# utiliser la fonction 'lmer' du package 'lme4' pour ajuster le modèle
library(lme4)
## Loading required package: Matrix
lmmodel2 <- lmer(formula = model2, 
               data = iris, 
               subset = Sepal.Length > 4.6)
print(lmmodel2)
## Linear mixed model fit by REML ['lmerMod']
## Formula: Sepal.Width ~ Petal.Width | Species
##    Data: iris
##  Subset: Sepal.Length > 4.6
## REML criterion at convergence: 66.3338
## Random effects:
##  Groups   Name        Std.Dev. Corr 
##  Species  (Intercept) 1.6829        
##           Petal.Width 0.6886   -0.96
##  Residual             0.2827        
## Number of obs: 141, groups:  Species, 3
## Fixed Effects:
## (Intercept)  
##       3.608
summary(lmmodel2)
## Linear mixed model fit by REML ['lmerMod']
## Formula: Sepal.Width ~ Petal.Width | Species
##    Data: iris
##  Subset: Sepal.Length > 4.6
## 
## REML criterion at convergence: 66.3
## 
## Scaled residuals: 
##      Min       1Q   Median       3Q      Max 
## -2.59701 -0.54821 -0.04085  0.57400  3.07229 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev. Corr 
##  Species  (Intercept) 2.83204  1.6829        
##           Petal.Width 0.47417  0.6886   -0.96
##  Residual             0.07989  0.2827        
## Number of obs: 141, groups:  Species, 3
## 
## Fixed effects:
##             Estimate Std. Error t value
## (Intercept)   3.6080     0.3292   10.96

3.3 Représenter les données

La visualisation graphique des données :

  • une étape clé pour examiner certains aspects des données
  • à la recherche de flexibilité et de simplicité pour construire et manipuler un graphique
  • géré historiquement par le package graphics (R Core Team 2018a)
  • réinventé par des packages comme grid (Murrell 2011, R Core Team (2018a)), lattice (Sarkar 2008), ggplot2 (Wickham 2016)

3.3.1 Les graphiques avec graphics (R Core Team 2018a)

  • plot : fonction centrale et générique pour représenter des données
  • Autres fonctions graphiques de haut niveau : boxplot(), hist(), image(), contours(), dotchart(), curve(), barplot(), stripchart(), pie(), …
  • Certaines fonctions de haut niveau renvoient les éléments statistiques qui ont permis de construire le graphique.
  • Fonctions graphiques de bas niveau (i.e. utilisables uniquement si une fonction graphique de haut niveau a été appelée auparavant) : points(), lines(), segments(), text(), abline(), legend(), mtext(), rect(), arrows(), polygon(), grid(), …
# 'attach' permet de ne plus répéter 'iris' avant chaque variable de ce jeu de données
attach(iris)
# créer un graphique en deux dimensions
plot(Sepal.Length, Petal.Length) 
# ajouter un titre
title("Graphique créé à l'aide des fonctions\ndu package graphics")

hist1 <- hist(Sepal.Length, plot = FALSE)
print(hist1)
## $breaks
## [1] 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0
## 
## $counts
## [1]  5 27 27 30 31 18  6  6
## 
## $density
## [1] 0.06666667 0.36000000 0.36000000 0.40000000 0.41333333 0.24000000
## [7] 0.08000000 0.08000000
## 
## $mids
## [1] 4.25 4.75 5.25 5.75 6.25 6.75 7.25 7.75
## 
## $xname
## [1] "Sepal.Length"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"
plot(hist1)

3.3.2 De nouvelles approches pour construire des graphiques

  • grid (Murrell 2011, R Core Team (2018a)) et ses grob (graphics objects), installé automatiquement avec R
  • lattice (Sarkar 2008) (installé automatiquement avec R) et son extension latticeExtra (Sarkar and Andrews 2016), basés sur les trellis
  • ggplot2 (Wickham 2016, Kassambara (2016)) et ses extensions ggvis (Chang and Wickham 2016), GGally (Schloerke et al. 2017), ggmap (Kahle and Wickham 2013), ggfortify (Tang, Horikoshi, and Li 2016)

  • Un graphique est un objet stockable et modifiable.
  • Les graphiques sont construits à partir d’un objet formula qui exprime la dépendance entre les variables à représenter.
  • Les objets graphiques sont esthétiquement plus modernes, plus facilement modifiables, plus facile à combiner.
  • En contrepartie, la grammaire liée à ces graphes se revèle plus complexe à appréhender pour construire des graphiques élaborés.

# version lattice
library(lattice)

# représenter 'Petal.Length' en fonction 'Sepal.Length'
xyplot(Petal.Length ~ Sepal.Length, data = iris)

# colorer les individus en fonction de la variable 'Species' et ajouter une légende
xyplot(Petal.Length ~ Sepal.Length, group = Species, 
       data = iris, auto.key = list(columns = nlevels(Species)))

# modifier le titre des axes, ajouter la grille en arrière plan et une courbe de régression (LOESS) et grossir la ligne de régression
xyplot(Petal.Length ~ Sepal.Length, data = iris,
       type = c("p", "g", "smooth"),
       xlab = "Length of Sepal", ylab = "Length of Petal",
       lwd = 4)

# réaliser une régression 'smooth' par 'Species'
xyplot(Petal.Length ~ Sepal.Length | Species, 
       group = Species, data = iris,
       type = c("p", "smooth"),
       scales = "free")

# version ggplot2
library(ggplot2)

# stocker le graphique de 'Petal.Length' en fonction 'Sepal.Length'
gg1 <- ggplot(data = iris, aes(x = Sepal.Length, y = Petal.Length)) 

# afficher 'gg1' pour constater qu'il est vide
gg1

# ajouter les points où les individus ont une couleur et une forme dépendant de la variable 'Species'
# ajouter également des titres aux axes et au graphique
gg2 <- gg1 + geom_point(aes(color = Species, shape = Species)) +
  xlab("Sepal Length") +  ylab("Petal Length") +
  ggtitle("Sepal-Petal Length")

# afficher 'gg2'
gg2

gg2 + facet_wrap(~ Species)

Quel système graphique choisir ?

  • si le projet est déjà avancé, tirer avantage de ce qui a déjà été réalisé et conserver le paradigme choisi
  • si le projet démarre et comporte des représentations graphiques majeures, choisir une approche de construction des graphes plus récente et donc utiliser les packages présentés dans ce document

3.3.3 Personnaliser et sauver les graphiques

La gestion des paramètres graphiques

  • dans graphics : par()
  • dans grid : gpar()
  • dans lattice : trellis.par.get() et trellis.par.set()
  • dans ggplot2 : ggthemes()

Quelques couleurs

  • rainbow() et grey() du package grDevices (R Core Team 2018a)
  • brewer.pal() du package RColorBrewer (Neuwirth 2014)

Sauver un graphique dans un fichier

Deux manières complémentaires de sauver le graphique en cours dans un fichier :

  • de manière iteractive (selon les IDE)
  • en ligne de commande R

Une fois le fichier créé, le rendu graphique (notamment concernant les couleurs et les aspects de transparence) peut différer :

  • selon le dispositif graphique utilisé (voir ?Devices du package grDevices (R Core Team 2018a) pour connaître les principaux dispositifs graphiques disponibles dans R)
  • selon le système d’exploitation

Sauver un graphique créé avec le package graphics :

# fermer les fenêtres graphiques en cours, pour éviter les ambiguïtés de l'objet graphique à enregistrer
graphics.off()

# choisir son dispositif graphique et le paramétrer
pdf(file = "nomFichierGraphique.pdf", width = 6, height = 6)

# construire son graphique avec `graphics`
plot(Sepal.Length, Petal.Length)

# fermer le dispositif graphique pour finaliser la sauvegarde du graphique
dev.off()

Sauver un graphique créé avec le package lattice :

# fermer les fenêtres graphiques en cours, pour éviter les ambiguïtés de l'objet graphique à enregistrer
graphics.off()

# choisir son dispositif graphique et le paramétrer
trellis.device(device = "pdf", file = "nomFichierGraphique.pdf", width = 6, height = 6)

# construire son graphique avec `lattice`
xyplot(Sepal.Length ~ Petal.Length, group = Species, 
       data = iris, auto.key = TRUE)

# fermer le dispositif graphique pour finaliser la sauvegarde du graphique
dev.off()

Sauver un graphique créé avec le package ggplot2 :

# construire son graphique avec 'ggplot2'
ggplot(data = iris, aes(x = Sepal.Length, y = Sepal.Width)) + 
    geom_point(aes(color = Species, shape = Species)) +
    xlab("Sepal Length") +  ylab("Sepal Width") +
    ggtitle("Sepal Length-Width")

# sauvegarder le dernier graphique créé dans un pdf
ggsave("nomFichierGraphique.pdf", width = 6, height = 6)

back to top

4 Quand R se surpasse

Historiquement, R a été développé afin d’offrir un outil simple et flexible pour traiter des données et réaliser des analyses statistiques. Il n’a pas été développé pour être performant en terme de puissance de calcul. La flexibilité a été préférée à la performance. C’est la raison pour laquelle R est souvent qualifié de lent, en comparaison à d’autres langages.

Cependant, il est toujours possible d’améliorer un code. Et une meilleure connaissance du logiciel R, de son organisation, de ses défauts, permet de développer des codes plus efficaces

4.1 Analyse des performances : benchmarking et profiling

  • Rester pragmatique : préférer passer du temps à analyser les données plutôt qu’à gagner quelques nanosecondes.
  • Se fixer un objectif de performance : la sur-optimisation peut être l’ennemie de la qualité et de la compréhension.
  • Ne pas aller au-devant des problématiques de performance : un bon code est un code qui remplit son rôle dans un temps qui semblera raisonnable à l’utilisateur.
  • Garder du recul sur les unités de temps : l’amélioration d’un code qui s’exécute déjà en quelques nanosecondes s’avèrera imperceptible.

  • Evaluating the Design of the R Language (Morandat et al. 2012)
  • R High Performance Programming (Lim and Tjhi 2015)

4.1.1 Evaluer le temps d’exécution d’un code

  • system.time() mesure le temps global (en secondes) d’exécution de n’importe quelle expression R.
# mesurer le temps d'exécution d'une expression R
system.time(runif(1e6))
##    user  system elapsed 
##   0.048   0.000   0.049

4.1.2 Répéter et comparer les temps d’exécution

  • Des facteurs externes (surcharge de R, mécanismes de cache, exécution d’autres tâches, …) peuvent impacter les temps d’exécution d’une expression.
  • Le package rbenchmark (avec la fonction benchmark) permet de répéter l’exécution d’une expression R et d’en mesurer le temps. Par défaut, chaque expression est répétée 100 fois.
  • Le package microbenchmark (avec la fonction microbenchmark) permet d’obtenir une distribution du temps d’exécution d’une expression répétée, mais également de comparer les distributions du temps d’exécution de plusieurs expressions. Par défaut, chaque expression est répétée 100 fois.
# utiliser le package 'rbenchmark' pour mesurer 10 fois le temps d'exécution
library(rbenchmark)
benchmark(runif(1e6), replications = 10)
##           test replications elapsed relative user.self sys.self user.child
## 1 runif(1e+06)           10   0.487        1      0.48    0.004          0
##   sys.child
## 1         0
# utiliser le package 'microbenchmark' pour mesurer 10 fois le temps d'exécution
library(microbenchmark)
microbenchmark(runif(1e6), times = 10)
## Unit: milliseconds
##          expr      min       lq     mean   median       uq      max neval
##  runif(1e+06) 48.41817 48.49952 49.37482 48.64768 51.03345 51.49573    10
# utiliser le package 'microbenchmark' pour comparer deux manières de calculer les racines carrrées
x <- runif(100)
microbenchmark(
    sqrt(x),
    x ^ 0.5, 
    times = 10
)
## Unit: microseconds
##     expr    min     lq    mean  median     uq    max neval
##  sqrt(x)  1.069  1.144  1.8670  1.1655  1.240  7.996    10
##    x^0.5 11.564 11.783 17.0652 12.4935 14.516 37.164    10

4.1.3 Identifier les goulots d’étranglement

  • Le but du profiling est d’identifier facilement et rapidement les goulots d’étranglement à l’intérieur d’un bloc de code.
  • Le principe est d’observer à intervalle régulier quelle fonction est en cours d’exécution.
  • La fonction Rprof() est une fonction intégrée à R.
  • Les packages proftools (Tierney and Jarjour 2016) (qui nécessite l’installation des packages Bioconductor graph et Rgraphviz) et profvis (Tierney and Jarjour 2016) (anciennement lineprof et profr, démo en ligne) proposent plusieurs outils pour détailler et visualiser les temps d’exécution d’un code.
  • Le profiling n’est pas disponible pour les fonctions C, ni pour les parties de code qui sont compilées.
# détailler avec 'Rprof' les temps d'exécutions de la succession des commandes appelées
library(ggplot2)
Rprof("Rprof.out")
gg1 <- ggplot(data = iris, aes(x = Sepal.Length, y = Petal.Length)) +
    geom_point(aes(color = Species, shape = Species)) +
    ggtitle("Sepal-Petal Length")
print(gg1)

Rprof(NULL)
summaryRprof("Rprof.out")$by.self
##                      self.time self.pct total.time total.pct
## "f"                       0.04    18.18       0.10     45.45
## "grid.Call.graphics"      0.04    18.18       0.06     27.27
## "eval"                    0.02     9.09       0.22    100.00
## "lapply"                  0.02     9.09       0.14     63.64
## "FUN"                     0.02     9.09       0.10     45.45
## "$<-"                     0.02     9.09       0.02      9.09
## "c"                       0.02     9.09       0.02      9.09
## "grobUnit"                0.02     9.09       0.02      9.09
## "rbind"                   0.02     9.09       0.02      9.09
# utiliser le package 'proftools' pour effectuer le profiling de l'exemple de la fonction 'glm'
install.packages("proftools")
source("http://bioconductor.org/biocLite.R")
biocLite(c("graph", "Rgraphviz"))
library(proftools)
plotProfileCallGraph(readProfileData("Rprof.out"), score = "total")
# utiliser le package 'lineprof' pour effectuer le profiling de l'exemple de la fonction 'glm'
library(profvis)
profvis({
    gg1 <- ggplot(data = iris, aes(x = Sepal.Length, y = Petal.Length)) +
        geom_point(aes(color = Species, shape = Species)) +
        ggtitle("Sepal-Petal Length")
    print(gg1)
})

4.2 Tracer et réparer les erreurs

Repérer les erreurs

  • La fonction traceback(), appelée dans la console à la suite d’une erreur, liste les commandes qui ont été appelées jusqu’à l’erreur.
  • La fonction browser() permet de suspendre l’exécution d’un code à l’endroit où cette fonction a été placée et à l’utilisateur d’explorer l’environnement à ce même endroit.
  • Le paramètre options(error = browser) permet l’ouverture automatique de l’explorateur de code dès qu’une erreur intervient.
  • Le paramètre options(warn = 2) permet de considérer les warnings comme des erreurs et donc de les tracer.
  • RStudio propose des solutions interactives qui remplacent l’appel aux fonctions traceback et browser().
# construire une imbrication de fonctions dont la dernière appelée renverra une erreur
f <- function(a) g(a)
g <- function(b) h(b)
h <- function(c) i(c)
i <- function(d) "a" + d
f(10)
## Error in "a" + d: argument non numérique pour un opérateur binaire
# afficher la liste des fonctions appelées jusqu'à l'erreur
traceback()

## 4: i(c) at #1
## 3: h(b) at #1
## 2: g(a) at #1
## 1: f(10)

Gérer les comportement qui génèrent des erreurs

  • La fonction try() permet d’ignorer les erreurs au sein d’un bloc de code et donc de poursuivre l’exécution d’un code même si celui-ci a généré des erreurs.
  • La fonction tryCatch() et withCallingHandlers() permettent de spécifier une action à réaliser en cas d’erreur.

Aller au devant des erreurs

  • Déboguer, c’est résoudre les problèmes qui n’ont pas été anticipés.
  • Le concept de defense programing consiste à faire en sorte que les erreurs soient détectées au plus tôt.
  • La fonction stopifnot() et le package assertthat (Wickham 2017) sont des outils utiles pour contrôler les erreurs potentielles au sein d’un code.
  • Il est recommandé de concevoir des situations reproductibles, des tests, pour caractériser des erreurs.
  • A chaque erreur détectée, un test peut être construit pour éviter que l’erreur ne se produise à nouveau.

4.3 Améliorer son R

Améliorer un code R nécessite d’améliorer ses connaissances du langage. Les livres, les supports de formations, les blogs et forums sont de bonnes ressources pour trouver de l’information, d’autant que la communauté autour de R est très importante et plutôt partageuse. Mais parfois, il suffit de discuter avec ses collègues pour se rendre compte que le problème a déjà été rencontré, parfois résolu, par quelqu’un d’autre.

4.3.1 Vectoriser

L’objet de base dans R étant le vecteur, il est naturel de se tourner vers l’arithmétique vectorielle pour améliorer les performances d’un code. Les fonctions de la famille apply() ont été développées pour faciliter la vectorisation des boucles, sans pour autant garantir de meilleures performances :

  • apply() pour appliquer une fonction aux lignes ou aux colonnes d’un objet
  • lapply() pour appliquer une fonction à tous les éléments d’une liste
  • tapply(), sapply(), vapply() et mapply()

D’autres fonctions vectorisées et écrites en C sont à préférer pour améliorer un code :

  • rowSums(), colSums(), rowMeans() et colMeans() renvoient la somme et la moyenne des lignes et des colonnes d’un objet
  • max.col() renvoie la position de colonne de la valeur maximale de chaque ligne d’une matrice
  • pmin() et pmax() renvoient les valeurs minimales et maximales d’un objet
# créer deux matrices de tailles différentes et les data frames correspondants
m7 <- matrix(runif(100), 10)
m8 <- matrix(runif(10000), 100)
df7 <- as.data.frame(m7)
df8 <- as.data.frame(m8)

# créer une fonction qui calcule la somme des élements de chaque ligne d'une matrice, à l'aide d'une boucle
f1 <- function(M) {
    somme <- numeric(nrow(M))
    for(i in seq_len(nrow(M))) somme[i] <- sum(M[i, ])
    return(somme)
}

# créer une fonction qui calcule la somme des élements de chaque ligne d'une matrice, à l'aide de la fonction 'apply'
f2 <- function(M) apply(M, 1, sum)

# créer une fonction qui calcule la somme des élements de chaque ligne d'une matrice, à l'aide de la fonction 'rowSums'
f3 <- function(M) rowSums(M)

# vérifier que les trois fonctions, appliquées à 'm7', renvoient les mêmes résultats 
all(f2(m7) == f1(m7))
## [1] TRUE
all(f3(m7) == f1(m7))
## [1] TRUE
# comparer les temps d'exécution des trois fonctions appliquées à 'm7'
microbenchmark(
    f1(m7),
    f2(m7),
    f3(m7)
)
## Unit: microseconds
##    expr    min      lq     mean  median      uq      max neval
##  f1(m7) 13.534 14.8130 15.98525 15.5255 16.1380   50.098   100
##  f2(m7) 37.723 40.1045 63.54538 41.8080 43.2515 2107.413   100
##  f3(m7) 20.392 22.5505 40.07812 25.0150 26.1895 1537.244   100
# comparer les temps d'exécution des trois fonctions appliquées à 'm8'
microbenchmark(
    f1(m8),
    f2(m8),
    f3(m8)
)
## Unit: microseconds
##    expr     min       lq      mean  median       uq      max neval
##  f1(m8) 176.990 181.9650 202.29649 187.025 198.9945  426.796   100
##  f2(m8) 316.749 326.8845 399.08595 336.218 350.8390 6021.106   100
##  f3(m8)  65.997  70.5075  76.14176  72.755  78.6265  120.858   100
# comparer les temps d'exécution des trois fonctions appliquées à 'df7'
microbenchmark(
    f1(df7),
    f2(df7),
    f3(df7)
)
## Unit: microseconds
##     expr      min        lq      mean    median        uq      max neval
##  f1(df7) 2213.373 2282.7760 2405.6060 2322.4065 2405.8250 5622.893   100
##  f2(df7)  144.383  156.8290  171.4965  168.2900  177.7785  433.441   100
##  f3(df7)  113.675  131.5405  153.5310  140.4345  151.6845 1314.703   100
# comparer les temps d'exécution des trois fonctions appliquées à 'df8'
microbenchmark(
    f1(df8),
    f2(df8),
    f3(df8)
)
## Unit: microseconds
##     expr        min         lq        mean     median         uq
##  f1(df8) 143787.472 144971.432 148237.9573 145705.286 146890.872
##  f2(df8)   1075.063   1128.111   1161.8435   1159.198   1191.653
##  f3(df8)    675.145    707.174    730.9566    723.454    743.387
##         max neval
##  321681.408   100
##    1288.993   100
##    1337.823   100

4.3.2 Gérer la mémoire

  • Computing thousands of test statistics simultaneously in R (Schwender and Müller 2012)

La gestion de la mémoire est souvent problématique dans R. En effet, les codes réalisent de nombreuses copies et de nombreuses conversions des données. Il est donc important d’en avoir conscience afin de construire et stocker ses variables de manière adaptée.

Plusieurs fonctions utiles donnent des informations sur l’utilisation de la mémoire par les objets :

  • tracemem() du package base (R Core Team 2018a) monitore les copies internes d’un objet.
  • address() et refs() du package pryr (Wickham 2018a) retournent respectivement l’adresse mémoire d’un objet et le nombre d’objets qui pointent sur une même adresse.

L’allocation dynamique des objets R amène de la souplesse au langage mais peut s’avérer coûteux dans de nombreux cas de programmation. La pré-allocation mémoire des objets peut ainsi permettre de gagner en perfomance sur un code.

# créer une fonction qui construit un vecteur en concaténant un à un les éléments
sans_alloc <- function(n){
    res <- c()
    for(i in seq_len(n)) res <- c(res, rnorm(1))
    return(res)
}

# créer une fonction qui remplit un vecteur pré-défini
avec_alloc <- function(n){
    res <- double(n)
    for(i in seq_len(n)) res[i] <- rnorm(1)
    return(res)
}

# comparer les temps d'exécution de la construction d'un même vecteur
microbenchmark(
    sans_alloc(1e4),
    avec_alloc(1e4),
    times = 10
)
## Unit: milliseconds
##               expr       min        lq      mean    median        uq
##  sans_alloc(10000) 250.04339 252.82650 276.84009 261.79812 262.71045
##  avec_alloc(10000)  24.52671  24.87539  25.64295  25.20679  25.69678
##        max neval
##  435.06634    10
##   29.91098    10

4.3.3 Paralléliser

  • Calcul parallèle avec R (Miele and Louvet 2016)
  • Parallel R (McCallum and Weston 2011)
  • Parallel computing for data science (Matloff 2015)
  • CRAN Task View: High-Performance and Parallel Computing with R

  • Par défaut, R est exécuté sur un seul thread, les opérations sont exécutées de manière séquentielle.
  • Envisageable grâce à l’architecture actuelle des ordinateurs et aux puissances de calcul mis à disposition de nos jours.
  • Quand un problème est la somme de problèmes indépendants.
  • Les boucles sont des problèmes de parallélisation embarassante.
  • La parallélisation repose sur des principes de processus père et de processus fils.

Le package parallel (R Core Team 2018a), inclus dans l’installation de R depuis sa version 2.14.0, est dérivé des packages snow (Tierney et al. 2016) et muticore (maintenant archivé).

  • detectCores() pour connaître le nombre de cœurs sur la machine
  • makeCluster() pour créer et paramétrer le cluster de processus fils
  • clusterExport() pour exporter, dans chaque processus fils (indépendants), une copie des objets nécessaires à leur exécution
  • stopCluster() pour arrêter les workers

  • Les fonctions parApply(), parLapply(), parSapply() sont respectivement les implémentations parallélisées de apply(), lapply() et sapply() (avec le mécanisme snow).
  • Les fonctions mclapply() et mcmapply() sont respectivement les implémentations parallélisées de lapply() et mapply() (avec le mécanisme multicore).

Le package foreach (Microsoft and Weston 2017) propose une nouvelle implémentation des boucles avec l’opérateur %do%. Grâce au package doParallel (Corporation and Weston 2017), les %do% devenant %dopar% permettent la parallélisation de ces boucles.

4.4 Interactions avec d’autres langages

4.4.1 R et C++ : la clé du succès

Pour gagner en efficacité, réécrire les fonctions clés en C++ est une voie prometteuse. Les avantages du C++ peuvent maintenant être exploitées dans R grâce à des packages performants qui ont favorisé l’usage des deux langages conjointement. Il suffit d’avoir un compilateur C++ installé sur sa machine !

Le package Rcpp (Eddelbuettel and François 2011, Eddelbuettel (2013), Eddelbuettel and Balamuta (2017)) fournit une API facile à prendre en main pour faire dialoguer R et C++. Quand le code est exécuté, Rcpp compile le C++ et construit une fonction R qui fait le lien avec la fonction compilée C++.

  • La fonction cppFunction() permet d’écrire du C++ en ligne à l’intérieur même d’un fichier R.
# programmer à l'aide d'une boucle, une fonction qui somme les éléments d'un vecteur
sumR <- function(x){
    total <- 0
    for(i in seq_along(x)){
        total <- total + x[i]
    }
    total
}

# programmer la même fonction en C++
library(Rcpp)
cppFunction('double sumC(NumericVector x){
    int n = x.size();
    double total = 0;
    for(int i = 0; i < n; i++){
        total += x[i];
    }
    return total;
}')

# comparer les temps de calcul de trois manières de calculer la somme des éléments d'un vecteur
x <- runif(1e3)
microbenchmark(
    sum(x),
    sumR(x),
    sumC(x)
)
## Unit: microseconds
##     expr    min     lq      mean  median      uq      max neval
##   sum(x)  1.948  1.981   2.10347  2.0145  2.0590    4.147   100
##  sumR(x) 76.747 76.909 123.58399 77.0605 77.3445 4669.321   100
##  sumC(x)  3.337  3.543  17.84894  3.6530  3.7975 1378.949   100
x <- runif(1e4)
microbenchmark(
    sum(x),
    sumR(x),
    sumC(x)
)
## Unit: microseconds
##     expr     min       lq      mean  median       uq     max neval
##   sum(x)  16.307  16.3765  17.12207  16.459  16.7300  51.051   100
##  sumR(x) 761.162 761.8270 772.12282 764.273 778.1495 969.981   100
##  sumC(x)  17.673  17.9565  18.57365  18.098  18.6160  27.780   100
  • La fonction sourceCpp() source un fichier .cpp dans lequel l’entête contiendra les deux lines suivantes :
#include <Rcpp.h>
using namespace Rcpp;

et dans lequel chaque fonction C++ qui voudra être utilisée dans R devra être précédé par

// [[Rcpp::export]]

D’autres packages permettent l’interaction entre R et C++ pour des problématiques plus ciblées :

  • inline (Sklyar et al. 2015)
  • RcppParallel (Allaire et al. 2018)
  • RcppArmadillo (Eddelbuettel and Sanderson 2014)
  • RcppEigen (Bates and Eddelbuettel 2013)

4.4.2 Les autres langages qui peuvent interagir avec R

  • Interfaces avec des bases de données : RPostgreSQL (Conway et al. 2017), RMySQL (Ooms et al. 2018), DBI (R Special Interest Group on Databases (R-SIG-DB), Wickham, and Müller 2018)
  • Interfaces avec JSON : RJSONIO (Lang 2014), jsonlite (Ooms 2014), rjson (Couture-Beil 2014)
  • Interfaces avec Jquery : DT (Xie 2018a)
  • Interfaces avec HTML : htmltools (RStudio and Inc. 2017), htmlwidgets (Vaidyanathan et al. 2018), crosstalk (Cheng 2016)
  • Interfaces avec Python : rPython (Bellosta 2015)

4.4.3 R pour la recherche reproductible

La recherche reproductible est aujourd’hui clairement mise en avant dans le cadre de la diffusion de résultats. Cette diffusion et ce partage des résultats et des codes qui ont permis de les obtenir peuvent se situer au sein d’un groupe de travail, au niveau d’un enseignement ou de la publication d’un article dans un journal scientifique. Il existe aujourd’hui plusieurs outils liés à R qui permettent de s’inscrire dans cette problématique de recherche reproductible.

Il est possible de construire un document alternant du texte et du code R (commandes et sorties). Deux systèmes majeurs cohabitent pour créer ce type de documents :

  • Sweave (dans le package utils (R Core Team 2018a)) intègre du R dans un document Latex.
  • Rmarkdown (dans le package rmarkdown (Allaire et al. 2017)) intègre du R dans un document markdown (grâce au package knitr (Xie 2018b, Xie (2015), Xie (2014)) et à Pandoc).

En complément, des outils interactifs et en ligne (qui ne nécessitent donc pas l’installation du logiciel R) permettent au développeur R de proposer à l’utilisateur un moyen de créer ou manipuler des résultats selon ces besoins.

  • Shiny
    • Learning Shiny (Resnizky 2015)
    • Package R (Chang et al. 2017)
    • Le développeur peut créer une interface web sans pour autant maîtriser le html.
    • L’utilisateur n’a pas besoin de connaître R pour mener une analyse ou pour explorer des résultats.
  • Jupyter
    • Application web pour diffuser des notebooks combinant du texte et du code
    • Des noyaux Julia, Python et R sont disponibles … entre autres !
    • Le navigateur devient un interpréteur interactif.

back to top

5 Conclusion

Pour cette demie-journée, l’approche était volontairement généraliste. Cette approche aura sûrement généré quelques frustrations auprès de ceux qui auraient souhaité récolter des éléments plus précis, plus thématiques. Dans ce cas, n’hésitez pas à venir discuter avec moi pour échanger sur d’autres aspects du langage, pour mettre en place d’autres formations, pour envisager d’autres pistes à explorer, …


Allaire, JJ, Romain Francois, Kevin Ushey, Gregory Vandenbrouck, Marcus Geelnard, and Intel. 2018. RcppParallel: Parallel Programming Tools for ’Rcpp’. https://CRAN.R-project.org/package=RcppParallel.

Allaire, JJ, Yihui Xie, Jonathan McPherson, Javier Luraschi, Kevin Ushey, Aron Atkins, Hadley Wickham, Joe Cheng, and Winston Chang. 2017. rmarkdown: Dynamic Documents for R. https://CRAN.R-project.org/package=rmarkdown.

Bache, Stefan Milton, and Hadley Wickham. 2014. magrittr: A Forward-Pipe Operator for R. https://CRAN.R-project.org/package=magrittr.

Bates, Douglas, and Dirk Eddelbuettel. 2013. “Fast and Elegant Numerical Linear Algebra Using the RcppEigen Package.” Journal of Statistical Software 52 (5): 1–24. http://www.jstatsoft.org/v52/i05/.

Bates, Douglas, and Martin Maechler. 2017. Matrix: Sparse and Dense Matrix Classes and Methods. https://CRAN.R-project.org/package=Matrix.

Bates, Douglas, Martin Mächler, Ben Bolker, and Steve Walker. 2015. “Fitting Linear Mixed-Effects Models Using lme4.” Journal of Statistical Software 67 (1): 1–48. doi:10.18637/jss.v067.i01.

Bellosta, Carlos J. Gil. 2015. rPython: Package Allowing R to Call Python. https://CRAN.R-project.org/package=rPython.

Burns, Patrick. 2012. The R Inferno. http://www.burns-stat.com/pages/Tutor/R_inferno.pdf.

Calenge, Clément. 2006. “The package adehabitat for the R software: tool for the analysis of space and habitat use by animals.” Ecological Modelling 197: 1035.

Chambers, John M. 2008. Software for Data Analysis, Programming with R. Edited by Springer. doi:10.1007/978-0-387-75936-4.

Chang, Winston, and Hadley Wickham. 2016. ggvis: Interactive Grammar of Graphics. https://CRAN.R-project.org/package=ggvis.

Chang, Winston, Joe Cheng, JJ Allaire, Yihui Xie, and Jonathan McPherson. 2017. shiny: Web Application Framework for R. https://CRAN.R-project.org/package=shiny.

Cheng, Joe. 2016. crosstalk: Inter-Widget Interactivity for HTML Widgets. https://CRAN.R-project.org/package=crosstalk.

Conway, Joe, Dirk Eddelbuettel, Tomoaki Nishiyama, Sameer Kumar Prayaga, and Neil Tiffin. 2017. RPostgreSQL: R Interface to the ’PostgreSQL’ Database System. https://CRAN.R-project.org/package=RPostgreSQL.

Corporation, Microsoft, and Steve Weston. 2017. doParallel: Foreach Parallel Adaptor for the ’parallel’ Package. https://CRAN.R-project.org/package=doParallel.

Couture-Beil, Alex. 2014. Rjson: JSON for R. https://CRAN.R-project.org/package=rjson.

Crawley, Michael J. 2013. The R Book. Edited by Wiley. doi:10.1002/9781118448908.

Delignette-Muller, Marie Laure, and Christophe Dutang. 2015. “fitdistrplus: An R Package for Fitting Distributions.” Journal of Statistical Software 64 (4): 1–34. http://www.jstatsoft.org/v64/i04/.

Dray, Stéphane, and Anne-Béatrice Dufour. 2007. “The ade4 package: implementing the duality diagram for ecologists.” Journal of Statistical Software 22 (4): 1–20.

Dray, Stéphane, Guillaume Blanchet, Daniel Borcard, Sylvie Clappe, Guillaume Guenard, Thibaut Jombart, Guillaume Larocque, Pierre Legendre, Naima Madi, and Helene H Wagner. 2018. adespatial: Multivariate Multiscale Spatial Analysis. https://CRAN.R-project.org/package=adespatial.

Eddelbuettel, Dirk. 2013. Seamless R and C++ Integration with Rcpp. New York: Springer. doi:10.1007/978-1-4614-6868-4.

Eddelbuettel, Dirk, and James Joseph Balamuta. 2017. “Extending R with C++: A Brief Introduction to Rcpp.” PeerJ Preprints 5 (August): e3188v1. doi:10.7287/peerj.preprints.3188v1.

Eddelbuettel, Dirk, and Romain François. 2011. “Rcpp: Seamless R and C++ Integration.” Journal of Statistical Software 40 (8): 1–18. doi:10.18637/jss.v040.i08.

Eddelbuettel, Dirk, and Conrad Sanderson. 2014. “RcppArmadillo: Accelerating R with high-performance C++ linear algebra.” Computational Statistics and Data Analysis 71 (March): 1054–63. http://dx.doi.org/10.1016/j.csda.2013.02.005.

Friedman, Jerome, Trevor Hastie, and Robert Tibshirani. 2010. “Regularization Paths for Generalized Linear Models via Coordinate Descent.” Journal of Statistical Software 33 (1): 1–22. http://www.jstatsoft.org/v33/i01/.

Friendly, Michael, and John Fox. 2016. matlib: Matrix Functions for Teaching and Learning Linear Algebra and Multivariate Statistics. https://CRAN.R-project.org/package=matlib.

Gagolewski, Marek. 2017. R package stringi: Character string processing facilities. http://www.gagolewski.com/software/stringi/.

Gelman, Andrew, and Yu-Sung Su. 2016. arm: Data Analysis Using Regression and Multilevel/Hierarchical Models. https://CRAN.R-project.org/package=arm.

Husson, Francois, Sebastien Le, and Marine Cadoret. 2017. SensoMineR: Sensory Data Analysis. https://CRAN.R-project.org/package=SensoMineR.

Jombart, Thibaut. 2008. “adegenet: a R package for the multivariate analysis of genetic markers.” Bioinformatics 24: 1403–5. doi:10.1093/bioinformatics/btn129.

Jombart, Thibaut, and Ismail Ahmed. 2011. “adegenet 1.3-1: new tools for the analysis of genome-wide SNP data.” Bioinformatics. doi:10.1093/bioinformatics/btr521.

Jombart, Thibaut, and Stéphane Dray. 2010. “adephylo: exploratory analyses for the phylogenetic comparative method.” Bioinformatics 26: 1907–9. doi:10.1093/bioinformatics/btq292.

Kahle, David, and Hadley Wickham. 2013. “ggmap: Spatial Visualization with ggplot2.” The R Journal 5 (1): 144–61. http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf.

Kassambara, Alboukadel. 2016. ggplot2: Guide to Create Beautiful Graphics in R. Edited by sthda.com. http://www.sthda.com/english/download/3-ebooks/5-guide-to-create-beautiful-graphics-in-r-book/.

Koenker, Roger, and Pin Ng. 2017. SparseM: Sparse Linear Algebra. https://CRAN.R-project.org/package=SparseM.

Lang, Duncan Temple. 2014. RJSONIO: Serialize R objects to JSON, JavaScript Object Notation. https://CRAN.R-project.org/package=RJSONIO.

Lê, Sébastien, Julie Josse, and François Husson. 2008. “FactoMineR: A Package for Multivariate Analysis.” Journal of Statistical Software 25 (1): 1–18. doi:10.18637/jss.v025.i01.

Lim, Aloysius, and William Tjhi. 2015. R High Performance Programming. Edited by Packt Publishing Ltd.

Maechler, Martin, Peter Rousseeuw, Anja Struyf, Mia Hubert, and Kurt Hornik. 2017. cluster: Cluster Analysis Basics and Extensions.

Matloff, Norman. 2011. The art of R Programming. Edited by No Starch Press. http://diytranscriptomics.com/Reading/files/The%20Art%20of%20R%20Programming.pdf.

———. 2015. Parallel computing for data science. Edited by Chapman & Hall. http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.467.9918&rep=rep1&type=pdf.

McCallum, Q. Ethan, and Stephen Weston. 2011. Parallel R. Edited by O’Reilly Media. http://detritus.fundacioace.com/pub/books/Oreilly.Parallel.R.Oct.2011.pdf.

Microsoft, and Steve Weston. 2017. foreach: Provides Foreach Looping Construct for R. https://CRAN.R-project.org/package=foreach.

Miele, Vincent, and Violaine Louvet. 2016. Calcul parallèle avec R. Edited by EDP Sciences. http://pbil.univ-lyon1.fr/members/miele/pratiqueR/.

Millot, Gaël. 2018. Comprendre et réaliser les tests statistiques à l’aide de R. Edited by De Boeck. Fourth.

Morandat, Floréal, Brandon Hill, Leo Osvald, and Jan Vitek. 2012. “Evaluating the Design of the R Language.” Edited by James Noble. Springer Berlin Heidelberg, 104–31. http://r.cs.purdue.edu/pub/ecoop12.pdf.

Murrell, Paul. 2011. R Graphics. Edited by Chapman & Hall. https://www.stat.auckland.ac.nz/~paul/RG2e/.

Neuwirth, Erich. 2014. RColorBrewer: ColorBrewer Palettes. https://CRAN.R-project.org/package=RColorBrewer.

Ooms, Jeroen. 2014. “The jsonlite Package: A Practical and Consistent Mapping Between JSON Data and R Objects.” arXiv:1403.2805 [Stat.CO]. https://arxiv.org/abs/1403.2805.

Ooms, Jeroen, David James, Saikat DebRoy, Hadley Wickham, and Jeffrey Horner. 2018. RMySQL: Database Interface and ’MySQL’ Driver for R. https://CRAN.R-project.org/package=RMySQL.

Pinheiro, Jose, Douglas Bates, Saikat DebRoy, Deepayan Sarkar, and R Core Team. 2018. nlme: Linear and Nonlinear Mixed Effects Models. https://CRAN.R-project.org/package=nlme.

Plummer, Martyn. 2016. rjags: Bayesian Graphical Models using MCMC. https://CRAN.R-project.org/package=rjags.

R Core Team. 2017. foreign: Read Data Stored by Minitab, S, SAS, SPSS, Stata, Systat, Weka, dBase, ... https://CRAN.R-project.org/package=foreign.

———. 2018a. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.

———. 2018b. Writing R Extensions. https://cran.r-project.org/doc/manuals/r-release/R-exts.html.

R Special Interest Group on Databases (R-SIG-DB), Hadley Wickham, and Kirill Müller. 2018. DBI: R Database Interface. https://CRAN.R-project.org/package=DBI.

Resnizky, Hernan G. 2015. Learning Shiny. Edited by Packt.

RStudio, and Inc. 2017. htmltools: Tools for HTML. https://CRAN.R-project.org/package=htmltools.

Sarkar, Deepayan. 2008. Lattice, Multivariate Data Visualisation with R. Edited by Springer. doi:10.1007/978-0-387-75969-2.

Sarkar, Deepayan, and Felix Andrews. 2016. latticeExtra: Extra Graphical Utilities Based on Lattice. https://CRAN.R-project.org/package=latticeExtra.

Schloerke, Barret, Jason Crowley, Di Cook, Francois Briatte, Moritz Marbach, Edwin Thoen, Amos Elberg, and Joseph Larmarange. 2017. GGally: Extension to ’ggplot2’. https://CRAN.R-project.org/package=GGally.

Schwender, Holger, and Tina Müller. 2012. “Computing thousands of test statistics simultaneously in R.” Statistical Computing & Graphics 18 (1). http://stat-computing.org/newsletter/issues/scgn-18-1.pdf.

Siberchicot, Aurélie, Alice Julien-Laferrière, Anne-Béatrice Dufour, Jean Thioulouse, and Stéphane Dray. 2017. “adegraphics: An S4 Lattice-Based Package for the Representation of Multivariate Data.” The R Journal 9 (2): 198–212. https://journal.r-project.org/archive/2017/RJ-2017-042/index.html.

Simon, Noah, Jerome Friedman, Trevor Hastie, and Rob Tibshirani. 2011. “Regularization Paths for Cox’s Proportional Hazards Model via Coordinate Descent.” Journal of Statistical Software 39 (5): 1–13. http://www.jstatsoft.org/v39/i05/.

Sklyar, Oleg, Duncan Murdoch, Mike Smith, Dirk Eddelbuettel, Romain Francois, and Karline Soetaert. 2015. inline: Functions to Inline C, C++, Fortran Function Calls from R. https://CRAN.R-project.org/package=inline.

Smith, David. 2017. CRAN Now Has 10,000 R Packages. Here’s How to Find the Ones You Need. http://blog.revolutionanalytics.com/2017/01/cran-10000.html.

Tang, Yuan, Masaaki Horikoshi, and Wenxuan Li. 2016. “ggfortify: Unified Interface to Visualize Statistical Result of Popular R Packages.” The R Journal 8 (2). https://journal.r-project.org/.

Thioulouse, Jean, and Stéphane Dray. 2007. “Interactive Multivariate Data Analysis in R with the ade4 and ade4TkGUI Packages.” Journal of Statistical Software 22 (5): 1–14.

Tierney, Luke, and Riad Jarjour. 2016. proftools: Profile Output Processing Tools for R. https://CRAN.R-project.org/package=proftools.

Tierney, Luke, A. J. Rossini, Na Li, and H. Sevcikova. 2016. snow: Simple Network of Workstations. https://CRAN.R-project.org/package=snow.

Vaidyanathan, Ramnath, Yihui Xie, JJ Allaire, Joe Cheng, and Kenton Russell. 2018. htmlwidgets: HTML Widgets for R. https://CRAN.R-project.org/package=htmlwidgets.

Wickham, Hadley. 2011. “The Split-Apply-Combine Strategy for Data Analysis.” Journal of Statistical Software 40 (1): 1–29. http://www.jstatsoft.org/v40/i01/.

———. 2015a. Advanced R. Edited by Chapman & Hall. http://adv-r.had.co.nz/.

———. 2015b. R Packages. Edited by O’Reilly. http://r-pkgs.had.co.nz/.

———. 2016. ggplot2, Elegant Graphics for Data Analysis. Edited by Springer. http://ggplot2.org/.

———. 2017. assertthat: Easy Pre and Post Assertions. https://CRAN.R-project.org/package=assertthat.

———. 2018a. pryr: Tools for Computing on the Language. https://CRAN.R-project.org/package=pryr.

———. 2018b. stringr: Simple, Consistent Wrappers for Common String Operations. https://CRAN.R-project.org/package=stringr.

Wickham, Hadley, and Lionel Henry. 2018. tidyr: Easily Tidy Data with ’spread()’ and ’gather()’ Functions. https://CRAN.R-project.org/package=tidyr.

Wickham, Hadley, Romain Francois, Lionel Henry, and Kirill Müller. 2017. Dplyr: A Grammar of Data Manipulation. https://CRAN.R-project.org/package=dplyr.

Xie, Yihui. 2014. “Knitr: A Comprehensive Tool for Reproducible Research in R.” In Implementing Reproducible Computational Research, edited by Victoria Stodden, Friedrich Leisch, and Roger D. Peng. Chapman; Hall/CRC. http://www.crcpress.com/product/isbn/9781466561595.

———. 2015. Dynamic Documents with R and knitr. 2nd ed. Boca Raton, Florida: Chapman; Hall/CRC. https://yihui.name/knitr/.

———. 2018a. DT: A Wrapper of the JavaScript Library ’DataTables’. https://CRAN.R-project.org/package=DT.

———. 2018b. knitr: A General-Purpose Package for Dynamic Report Generation in R. https://yihui.name/knitr/.


  1. Il y un miroir CRAN sur le campus de la Doua, physiquement situé au LBBE : https://pbil.univ-lyon1.fr/CRAN/

  2. Si vous travaillez sous RStudio, ces guides sont accessibles de manière interactive dans la rubrique Manuals de l’onglet Help/R Help

  3. De ce fait, il est recommandé d’éviter l’utilisation du . dans le nom des objets R afin d’éviter les ambiguïtés.