Abstract
R est à la fois logiciel (libre et gratuit) et langage, orienté vers l’analyse statistique de données. Dans un premier temps, l’écosystème de R sera présenté ainsi que les éléments de base de sa syntaxe, dans le but de réaliser des analyses statistiques et en représenter graphiquement les résultats dans R. Dans un deuxième temps, les programmeurs plus familiers avec R pourront suivre les pistes proposées pour sérieusement améliorer leurs codes et faire interagir R avec d’autres langages/outils afin de compléter leur offre logicielle.
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
R est orienté vers le traitement des données et l’analyse statistique.
R est essentiellement codé en C, R et Fortran.
Le R Journal paraît deux fois par an et les article sont en accès libre et soumis à un comité de lecture.
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)
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 :
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 :
Côté grand public, il existe principalement deux plateformes d’hébergement :
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.
getwd()
.setwd("/chemin/du/repertoire/que/je/veux")
..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
La documentation officielle de R
Se documenter dans R
?nomFctn
ou help("nomFctn")
.example(nomFctn)
.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
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)'.
#
.;
à la fin des lignes de commande.<-
permet d’affecter une valeur (élément de droite) à une variable (élément de gauche).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.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.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
is.numeric()
, is.double()
, is.integer()
as.numeric()
, as.double()
, as.integer()
Les facteurs
factor
is.factor()
as.factor()
levels
définissant l’ensemble des valeurs que peut prendre le facteur.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
is.character()
as.character()
paste()
letters
, LETTERS
, month.abb
, month.name
Les valeurs booléennes
TRUE
et FALSE
is.logical()
as.logical()
!
, &
, |
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
.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.TRUE
Les vecteurs
vector()
is.vector()
as.vector()
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
matrix()
is.matrix()
as.matrix()
cbind()
, rbind()
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
data.frame
est une structure spécifique à R.data.frame()
is.data.frame()
as.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
list()
is.list()
as.list()
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
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.for
incrémente elle-même l’itérateur.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
Utiliser une fonction existante
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.# 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
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.# 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
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).
class()
renseigne sur la classe d’un objetinherits()
teste si un objet hérite d’une classe particulière
S3
base
(R Core Team 2018a) et stats
(R Core Team 2018a)en contrepartie, la protection des objets n’est pas garantie
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
# 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
UseMethod()
.$
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
methods
(inclus dans l’installation de base de R) contient tout le code relatif à la mise en place du S4 dans Rtrès développé dans Bioconductor, du fait de la complexité des données
new()
crée un nouvel objet d’une classe.new()
pour créer un nouvel objet.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 classeprototype
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.@
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
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.
Transformer les données :
sort()
, order()
et rank()
pour trier et ordonner un vecteurv4 <- 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 objetdf3 <- 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
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èmecut()
pour couper un vecteur en plusieurs sections et le convertir en facteurwith()
pour évaluer une expression dans un environnement de donnéesna.fail()
, na.exclude()
, na.pass()
pour traiter les NA
Le package plyr
(Wickham 2011)
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)
filter()
, arrange()
, select()
, rename()
, mutate()
, transmute()
, summarise()
Et d’autres
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’analysesummary()
: pour afficher un résumé détaillé de l’analyseset.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.Fonctions mathématiques courantes
sum()
, cumsum()
: somme, somme cumuléeprod()
, cumprod()
: produit, produit cummulémin()
, max()
: valeurs minimales et maximaleslog()
, exp()
: logarithme et exponentiellesqrt()
: racine carréeFonctions de statistiques descriptives
mean()
: moyennemediane()
: médianequantile()
: quantilesvar()
: variancesd()
: écart-typecor()
: corrélationcov()
: covarianceAppliqué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 matriciellediag()
: pour renvoyer la diagonale d’une matrice ou pour créer un matrice diagonaledet()
et determinant()
: déterminant de matricesolve()
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)
Dans le package stats
(R Core Team 2018a), de nombreuses distributions de probabilité sont disponibles :
beta
: betabinom
: binomialecauchy
: Cauchychisq
: Chi-deuxexp
: exponentielleF
: F de Fishergamma
: gammageom
: géométriquehyper
: hypergéométriquelnorm
: log-normalelogis
: logistiquenbinom
: binomiale négativenorm
: normalepois
: Poissonsignrank
: statistique des rangs signés de Wilcoxont
: t de Studentunif
: uniformeweibull
: Weibullwilcox
: somme des rangs de WilcoxonQuatre fonctions sont associées à chaque distribution. Elles sont appelées en précédant la nom de la distribution par le suffixe approprié :
d
pour obtenir la densité de probabilitép
pour obtenir la fonction de distributionq
pour obtenir la fonction des quantilesr
pour générer aléatoirement des nombres appartenant à la distributionpar(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))
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éesbartlett.test()
: Test de Bartlett d’homogénéité de variancesbinom.test()
: Test Binomial exactchisq.test()
: Test du Chi2cor.test()
: Test de corrélation de Pearson, de Kendall ou de Spearmanfisher.test()
: Test exact de Fisher pour données de comptaget.test()
: t-Test de Student de comparaison de moyennesvar.test()
: Test F de Fisher de comparaison de varianceswilcox.test()
: Test de rang de Wilcoxonks.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)
stats
(R Core Team 2018a) contient également des fonctions pour mener des analyses exploratoires sur les données :
hclust()
: classification hiérarchiquekmeans()
: classification par la méthode des k-meansdist()
: calcul de matrices de distanceprcomp()
: analyse des composantes principalesCependant, des packages spécialisés pour traiter ces questions sont plus complets et proposent un grand nombre de méthodes d’analyses :
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éesarm
(Gelman and Su 2016) : régression and modèles multi-niveaux et hiérarchiquesdata("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)
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ésiducoef()
: retourne les coefficients estimésresiduals()
: retourne les résidusfitted()
: retourne les valeurs ajustées par le modèlelogLik()
: calcule la vraisemblance et le nombre de paramètres d’un modèleAIC()
: calcule le critère d’information d’Akaikeanova()
: table d’analyse de la varianceAjuster un modèle
aov()
: ajustement d’une analyse de variancelm()
: ajustement d’un modèle linéaireglm()
: 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’AICPackages 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 mixteslme4
(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éairesglmnet
(Friedman, Hastie, and Tibshirani 2010, Simon et al. (2011)) : fonctions pour modèles Lasso et Elastic-Netfitdistrplus
(Delignette-Muller and Dutang 2015) : fonctions pour ajuster des distributions paramétriques à des données censurées et non-censuréesrjags
(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
La visualisation graphique des données :
graphics
(R Core Team 2018a)grid
(Murrell 2011, R Core Team (2018a)), lattice
(Sarkar 2008), ggplot2
(Wickham 2016)graphics
(R Core Team 2018a)plot
: fonction centrale et générique pour représenter des donnéesboxplot()
, hist()
, image()
, contours()
, dotchart()
, curve()
, barplot()
, stripchart()
, pie()
, …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)
grid
(Murrell 2011, R Core Team (2018a)) et ses grob (graphics objects), installé automatiquement avec Rlattice
(Sarkar 2008) (installé automatiquement avec R) et son extension latticeExtra
(Sarkar and Andrews 2016), basés sur les trellisggplot2
(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)
formula
qui exprime la dépendance entre les variables à représenter.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 ?
La gestion des paramètres graphiques
graphics
: par()
grid
: gpar()
lattice
: trellis.par.get()
et trellis.par.set()
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 :
Une fois le fichier créé, le rendu graphique (notamment concernant les couleurs et les aspects de transparence) peut différer :
?Devices
du package grDevices
(R Core Team 2018a) pour connaître les principaux dispositifs graphiques disponibles dans R)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)
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
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.
R High Performance Programming (Lim and Tjhi 2015)
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
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.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
Rprof()
est une fonction intégrée à R.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.# 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)
})
Repérer les erreurs
traceback()
, appelée dans la console à la suite d’une erreur, liste les commandes qui ont été appelées jusqu’à l’erreur.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.options(error = browser)
permet l’ouverture automatique de l’explorateur de code dès qu’une erreur intervient.options(warn = 2)
permet de considérer les warnings
comme des erreurs et donc de les tracer.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
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.tryCatch()
et withCallingHandlers()
permettent de spécifier une action à réaliser en cas d’erreur.Aller au devant des erreurs
stopifnot()
et le package assertthat
(Wickham 2017) sont des outils utiles pour contrôler les erreurs potentielles au sein d’un code.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.
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 objetlapply()
pour appliquer une fonction à tous les éléments d’une listetapply()
, 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 objetmax.col()
renvoie la position de colonne de la valeur maximale de chaque ligne d’une matricepmin()
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
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
CRAN Task View: High-Performance and Parallel Computing with R
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 machinemakeCluster()
pour créer et paramétrer le cluster de processus filsclusterExport()
pour exporter, dans chaque processus fils (indépendants), une copie des objets nécessaires à leur exécutionstopCluster()
pour arrêter les workers
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.
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++.
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
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 :
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)RJSONIO
(Lang 2014), jsonlite
(Ooms 2014), rjson
(Couture-Beil 2014)DT
(Xie 2018a)htmltools
(RStudio and Inc. 2017), htmlwidgets
(Vaidyanathan et al. 2018), crosstalk
(Cheng 2016)rPython
(Bellosta 2015)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 :
utils
(R Core Team 2018a)) intègre du R dans un document Latex.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.
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/.
Il y un miroir CRAN sur le campus de la Doua, physiquement situé au LBBE : https://pbil.univ-lyon1.fr/CRAN/↩
Si vous travaillez sous RStudio, ces guides sont accessibles de manière interactive dans la rubrique Manuals de l’onglet Help/R Help↩
De ce fait, il est recommandé d’éviter l’utilisation du .
dans le nom des objets R afin d’éviter les ambiguïtés.↩