Packages R - Département de mathématiques et de statistique

Transcription

Packages R - Département de mathématiques et de statistique
Packages R
Sophie Baillargeon, Université Laval
26 mars 2015
Contents
Utilisation de packages R
2
Installation et chargement d’un package R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Différentes façons d’installer un package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Accéder au contenu d’un package R chargé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
Fonctions publiques versus privées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
Jeux de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
Code source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
Création de packages R
8
Étape 1. Écrire les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
Étape 2. Créer la bonne structure de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Dossier nommé “R” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Dossier nommé “man” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Fichier nommé “DESCRIPTION” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Fichier nommé “NAMESPACE” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Autres fichiers et dossiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
Étape 3. Écrire la Documentation des fonctions et du package . . . . . . . . . . . . . . . . . . . .
10
Comment écrire de la documentation avec roxygen2? . . . . . . . . . . . . . . . . . . . . . .
11
Comment générer les fichiers .Rd et le fichier NAMESPACE ? . . . . . . . . . . . . . . . . . .
14
Étape 4. Compiler et vérifier le package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
Sous-étape a) Créer un projet RStudio avec notre package . . . . . . . . . . . . . . . . . . . .
14
Sous-étape b) Configurer les options de RStudio . . . . . . . . . . . . . . . . . . . . . . . . .
14
Sous-étape c) Compiler à partir du menu Build de RStudio . . . . . . . . . . . . . . . . . . .
15
Étape 5. Au besoin, mettre à jour le package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
Références
16
1
Utilisation de packages R
Lors de l’ouverture d’une session R, nous avons accès à un bon nombre de fonctions et de jeux de données.
Ces objets R sont accessibles, car ils proviennent de packages R chargés automatiquement à l’ouverture de
session.
Un package R est simplement un regroupement de fonctions et de données documentées.
Installation et chargement d’un package R
Il est simple de charger en R des packages supplémentaires à ceux chargés par défaut. Il suffit d’utiliser la
commande library comme dans cet exemple :
library(ggplot2)
Cette commande fonctionne uniquement si le package a été préalablement installé sur notre ordinateur.
L’installation d’un package et le chargement d’un package sont donc deux étapes distinctes.
L’installation n’a pas à être faite à chaque fois que le package est chargé. On doit la faire la première fois
que l’on souhaite utiliser le package, puis à chaque fois que l’on met R à jour. Tout comme le logiciel R, les
packages sont périodiquement mis à jour par leurs auteurs. On désirera donc parfois les réinstaller afin de les
mettre à jour.
En RStudio, il est facile de voir la liste des packages installés sur son ordinateur pour la version de R utilisée.
On retrouve cette liste dans la sous-fenêtre Packages.
Différentes façons d’installer un package
L’installation de package a déjà été abordée dans le Guide d’installation ou de mise à jour de R et RStudio.
Voici de l’information plus détaillée à ce sujet.
À partir du CRAN : Le CRAN est le dépôt informatique de packages géré par le R core team. C’est là
que la majorité des packages R sont rendus disponibles publiquement. Pour installer un package à partir
d’un des miroirs du CRAN, on utilise la fonction install.packages comme dans cet exemple :
install.packages("ggplot2")
Cette commande lance le téléchargement du fichier compressé d’installation du package, puis lance la décompression du fichier dans le dossier approprié. Bien sûr, il faut être connecté à internet pour que la commande
fonctionne. La version du package correspondant à notre système d’exploitation est automatiquement
sélectionnée :
• .tar.gz (package source) pour Linux/Unix,
• .zip pour Windows,
• .tgz pour OS X (Mac).
Aussi, install.packages télécharge et installe par défaut les packages dont dépend le package qui nous
intéresse. Cette option est très pratique, car certains packages dépendent d’un grand nombre de packages
(ggplot2 en est un bon exemple).
RStudio offre une fonctionnalité pour rendre encore plus conviviale l’installation de packages. Dans la
sous-fenêtre Packages, le bouton Install (en haut à gauche) permet d’installer des packages. En fait, cette
fonctionnalité ne fait qu’écrire et soumettre la commande install.packages en fonction des options choisies
par l’utilisateur.
2
À partir d’un fichier compressé d’installation : Afin d’installer un package non publicisé, qui n’est
pas téléchargeable sur le web, on doit avoir sur notre ordinateur le fichier compressé d’installation du package
correspondant à notre système d’exploitation (ou le package source). On installe le package avec la commande
install.packages comme dans cet exemple :
install.packages("C:/R/coursR/ggplot2_1.0.1.zip", repos = NULL)
On peut aussi utiliser cette façon de faire si on télécharge manuellement le fichier compressé d’installation du
package, par exemple à partir du site web personnel de l’auteur du package.
Cette technique est aussi utile lorsque nous avons besoin d’une ancienne version d’un package. Si on laisse
install.packages télécharger du CRAN un package, il téléchargera la dernière version du package. Parfois,
des mises à jour de package rendent certains de nos programmes non fonctionnels et on souhaite continuer
d’utiliser une version antérieure du package. Pour installer une version d’un package qui n’est pas sa dernière
version, il faut aller sur sa page web du CRAN (par exemple http://CRAN.R-project.org/package=ggplot2),
et aller télécharger manuellement la version dont on a besoin dans Old Sources.
Ce type d’installation peut se réaliser par le menu Install de la sous-fenêtre Packages de RStudio, en
sélectionnant : Install from: -> Package Archive File.
À partir d’un dépôt informatique autre que le CRAN : En plus du CRAN, on retrouve des packages
R à d’autres endroits sur le web, notamment sur :
• le dépôt informatique de packages en bio-informatique Bioconductor :
des instructions d’installation sont disponibles sur la page web : http://www.bioconductor.org/install/,
• un service wed d’hébergement et de gestion de développement de logiciels tel que Github ou Bitbucket :
le package R devtools offre des fonctions pour télécharger et installer directement à partir de ces sites
(ex. fonctions install_github et install_bitbucket).
Accéder au contenu d’un package R chargé
Une fois un package chargé en R avec la commande library, on peut accéder à son contenu dans la session
R. On a vu dans le cours sur les calculs statistiques et mathématiques en R comment fonctionne l’évaluation
d’expressions en R. On sait donc que le chargement d’un nouveau package ajoute un environnement dans le
chemin de recherche de R, juste en dessous de l’environnement de travail. Cet environnement contient les
fonctions publiques et les données du package.
Fonctions publiques versus privées
Dans la phrase précédente, le mot publiques n’est pas anodin. Les fonctions publiques d’un package sont
celles destinées à être appelées par des utilisateurs. Un package peut aussi contenir des fonctions privées (ou
internes, ou cachées) qui sont uniquement destinées à être appelées par d’autres fonctions du package.
Les fonctions privées sont très utiles pour partitionner du code en bloc de calculs indépendants. Elles sont
principalement utiles pour éviter de répéter des bouts de code. Si un calcul doit être exécuté fréquemment
par les fonctions d’un package, le développeur peut choisir de répéter un même bout de code pour ce calcul
aux endroits appropriés dans le code source. Cependant, la présence de bouts de code identiques dans un
programme est une mauvaise pratique de programmation. Si on a besoin de modifier le calcul fait dans ces
bouts de code, il faut penser à aller faire les modifications à tous les endroits où le code est répété. Il est
risqué d’oublier de modifier un des bouts. Si au contraire, on a créé une fonction pour faire le calcul, la
modification doit être faite à un seul endroit. On gagne du temps à long terme, le code est plus clair et on
minimise les risques d’erreur. En informatique, on appelle ce principe Don’t Repeat Yourself . Appliquer ce
principe est une bonne pratique de programmation.
3
Environnement d’un package dans le chemin de recherche : On peut lister le contenu de
l’environnement ajouté dans le chemin de recherche de R lors du chargement d’un package avec la fonction
ls comme dans l’exemple suivant :
ls("package:stats")
## [1] "acf"
"acf2AR"
## [4] "add1"
"addmargins"
## [7] "aggregate.data.frame" "aggregate.ts"
"add.scope"
"aggregate"
"AIC"
Seulement les 9 premiers éléments de la liste sont affichés ici, car cette liste compte en réalité 446 éléments.
Espace de noms (namespace) d’un package : Il est aussi possible de lister tout le contenu d’un package,
public ou privé, grâce à la fonction getNamespace, comme dans l’exemple suivant
ls(getNamespace("stats"))
## [1] "[.acf"
## [5] "[.tskernel"
"[.formula"
"[.terms"
"[[.dendrogram" "[<-.ts"
"[.ts"
"acf"
Seulement les 8 premiers éléments de la liste sont affichés ici, car cette liste compte en réalité 1091 éléments.
Cet environnement, où tout le contenu d’un package est présent, se nomme espace de noms (en anglais
namespace). L’espace de nom n’est pas dans le chemin de recherche de R, mais son contenu est tout de même
accessible grâce à l’opérateur ::: et à des fonctions telles que getAnywhere et getS3method.
Par exemple, le package stats contient la fonction privée Tr qui permet de calculer la trace d’une matrice. Il
n’est pas possible d’accéder directement à cette fonction, c’est-à-dire à partir du chemin de recherche.
Tr
## Error in eval(expr, envir, enclos): objet 'Tr' introuvable
On arrive cependant à y accéder par les commandes suivantes :
stats:::Tr
##
##
##
##
function (matrix)
sum(diag(matrix))
<bytecode: 0x00000000062e4dc0>
<environment: namespace:stats>
getAnywhere(Tr)
##
##
##
##
##
##
##
##
##
A single object matching 'Tr' was found
It was found in the following places
namespace:stats
with value
function (matrix)
sum(diag(matrix))
<bytecode: 0x00000000062e4dc0>
<environment: namespace:stats>
4
Aussi la méthode S3 pour la fonction générique plot fait partie du package stats, mais elle n’est pas publique.
plot.lm
## Error in eval(expr, envir, enclos): objet 'plot.lm' introuvable
On peut tout de même y accéder avec la fonction getS3method
args(getS3method("plot", "lm"))
## function (x, which = c(1L:3L, 5L), caption = list("Residuals vs Fitted",
##
"Normal Q-Q", "Scale-Location", "Cook's distance", "Residuals vs Leverage",
##
expression("Cook's dist vs Leverage " * h[ii]/(1 - h[ii]))),
##
panel = if (add.smooth) panel.smooth else points, sub.caption = NULL,
##
main = "", ask = prod(par("mfcol")) < length(which) && dev.interactive(),
##
..., id.n = 3, labels.id = names(residuals(x)), cex.id = 0.75,
##
qqline = TRUE, cook.levels = c(0.5, 1), add.smooth = getOption("add.smooth"),
##
label.pos = c(4, 2), cex.caption = 1)
## NULL
On aurait aussi pu y accéder avec ::: ou getAnywhere.
Environnement englobant des fonctions d’un package : Dans le cours Création de fonctions en
R, le sujet de l’exécution d’une fonction est abordé. On y parle d’environnement englobant, qui permet
de déterminer le chemin de recherche utilisé lors de l’exécution d’une fonction. Quel est l’environnement
englobant des fonctions d’un package? Il s’agit de l’espace de noms du package, comme en fait foi l’exemple
suivant.
environment(var)
## <environment: namespace:stats>
C’est pour cette raison que les fonctions d’un package peuvent accéder directement aux fonctions internes du
package. Donc, dans le code source d’un package, on n’a pas besoin d’utiliser ::: ou getAnywhere pour
utiliser des fonctions internes.
Le chemin de recherche complet lors de l’exécution d’une fonction dans un package chargé est le suivant :
1.
2.
3.
4.
5.
6.
l’environnement local d’exécution de la fonction,
l’environnement englobant de la fonction, soit l’espace de noms du package,
l’environnement des objets importés par le package,
l’environnement du package R de base,
l’environnement de travail,
les environnements de tous les packages chargés.
Ce chemin va nous aider à déterminer quels objets R peuvent être utilisés dans le corps de fonctions incluses
dans un package que l’on crée (vu plus loin). Un des environnements de cette liste n’a jamais été mentionné
auparavant : l’environnement des objets importés par le package. Il s’agit de la liste des fonctions ne provenant
pas directement du package, ou encore du package R de base, qui sont utilisées dans le package.
5
Jeux de données
Parfois, les jeux de données inclus dans un package se retrouvent directement dans l’environnement d’un
package dans le chemin de recherche. C’est le cas par exemple des jeux de données du package datasets.
ls("package:datasets")
## [1] "ability.cov"
## [5] "anscombe"
"airmiles"
"attenu"
"AirPassengers" "airquality"
"attitude"
"austres"
Seulement les 8 premiers éléments de la liste sont affichés ici, car cette liste compte en réalité 103 éléments.
Cependant, les jeux de données sont parfois cachés. Ils sont traités différemment des fonctions privées et ne
se retrouvent même pas dans l’espace de noms du package. C’est le cas par exemple dans le package copula.
library(copula)
La fonction data est très utile dans ce cas. Cette fonction a plusieurs utilités. Premièrement, elle permet
d’énumérer tous les jeux de données contenus dans un package.
data(package = "copula")
Le résultat est affiché dans une fenêtre indépendante, pas dans la console. On apprend que le pacakge copula
contient un jeu de données nommé uranium. Cependant, ce jeu de données est caché et on ne peut pas y
accéder directement.
str(uranium)
## Error in str(uranium): objet 'uranium' introuvable
La fonction data permet alors de charger le jeu de données dans notre environnement de travail.
data(uranium)
str(uranium)
## 'data.frame':
655 obs. of 7 variables:
## $ U : num 0.544 0.591 0.531 0.633 0.568 ...
## $ Li: num 1.57 1.34 1.41 1.34 1.2 ...
## $ Co: num 1.03 1.17 1.01 1.06 1.01 ...
## $ K : num 4.21 4.34 4.22 4.16 4.22 ...
## $ Cs: num 1.66 1.92 1.85 1.85 1.73 ...
## $ Sc: num 0.839 0.934 0.903 0.908 0.763 ...
## $ Ti: num 3.57 3.38 3.7 3.66 3.44 ...
Cette pratique de cacher les jeux de données d’un package tend à disparaître.
6
Documentation
Tout package doit obligatoirement contenir de la documentation sous forme de fiches d’aide. Ces fiches d’aide
s’ouvrent avec la fonction help ou l’opérateur ? lorsque l’on connaît le nom de la fonction pour laquelle on
veut afficher la documentation. Les éléments suivants sont toujours documentés dans une fiche d’aide :
•
•
•
•
les fonctions publiques,
les méthodes pour des fonctions génériques,
les jeux de données,
le package lui-même.
Une fiche d’aide peut servir à documenter plus d’un élément (par exemple un groupe de fonctions similaires).
On ouvrir toute la documentation d’un package en passant par :
help.start() -> Packages -> nom du package.
On a ainsi accès aux fiches d’aide, mais aussi à un fichier descriptif du package, parfois à des guides d’utilisation
(souvent appelées vignettes), à un fichier NEWS documentant les changements apportés au package lors de
mises à jour, etc.
Pour les packages sur le CRAN, toutes les fiches d’aide et le fichier descriptifs sont regroupés dans un fichier
PDF. On retrouve ce PDF directement sur le CRAN (dans Reference manual), et non par le fenêtre d’aide
de R (par exemple http://cran.r-project.org/web/packages/ggplot2/ggplot2.pdf).
La documentation sert à expliquer comment utiliser les fonctions et à décrire ce que permettent de faire les
fonctions. Il arrive (assez fréquemment malheureusement) que les fiches d’aide soient peu bavardes à propos
des calculs effectués par une fonction. La fiche d’aide contient parfois des références qui peuvent nous éclairer.
Si ce n’est pas le cas, on est parfois contraint d’aller voir directement dans le code source pour comprendre ce
que fait une fonction.
Code source
Étant donné que R est un logiciel libre, on peut avoir accès au code source du R de base, ainsi qu’à celui de
n’importe quel package R. Accéder au code source est parfois simple. Il suffit de soumettre le nom d’une
fonction dans la console (sans parenthèses) pour que le code source de la fonction soit affiché. On peut aussi
faire afficher ce code dans une fenêtre indépendante avec la fonction edit. Pour les fonctions cachées, il faut
utiliser ::: ou getAnywhere comme mentionné ci-dessus.
Pour certaines fonctions, le code source est par contre écrit dans un autre langage que R. Par exemple, le
code R de la fonction var du package stats contient uniquement de la validation d’arguments.
var
## function (x, y = NULL, na.rm = FALSE, use)
## {
##
if (missing(use))
##
use <- if (na.rm)
##
"na.or.complete"
##
else "everything"
##
na.method <- pmatch(use, c("all.obs", "complete.obs", "pairwise.complete.obs",
##
"everything", "na.or.complete"))
##
if (is.na(na.method))
##
stop("invalid 'use' argument")
7
##
if (is.data.frame(x))
##
x <- as.matrix(x)
##
else stopifnot(is.atomic(x))
##
if (is.data.frame(y))
##
y <- as.matrix(y)
##
else stopifnot(is.atomic(y))
##
.Call(C_cov, x, y, na.method, FALSE)
## }
## <bytecode: 0x00000000045828e0>
## <environment: namespace:stats>
Le coeur du calcul est fait dans une fonction C, appelée à la dernière ligne du corps de la fonction à l’aide de
la fonction .Call. Il est aussi possible de voir ce code C. On le trouvera dans les fichiers d’installation de R.
L’article suivant explique comment faire.
Ligges, U. (2006). R Help Desk: Accessing the Sources. R News, vol. 6, no. 4, p. 43-45. http://cran.r-project.
org/doc/Rnews/Rnews_2006-4.pdf
Création de packages R
Pour créer un package R, il faut d’abord développer une structure de fichiers similaires à ce que l’on retrouve
dans n’importe quel package source. Pour voir de quoi à l’air une telle structure de fichier, il suffit de :
• télécharger un package source à partir du CRAN (par exemple ggplot2_1.0.1.tar.gz sur http://CRAN.
R-project.org/package=ggplot2),
• décompresser le fichier (il y a 2 étapes de décompression à effectuer).
L’exemple utilisé ici, soit le package ggplot2, est un gros package. Seuls certains de ses fichiers et dossiers
sont obligatoires dans tout package.
Après avoir développé les fichiers sources, il faut compiler le package. Pour faire cette étape sur Windows, il
faut d’abord s’assurer d’avoir les bonnes installations. Les Rtools doivent être installés sur notre ordinateur
(voir le guide d’installation ou de mise à jour de R et RStudio).
Étape 1. Écrire les fonctions
Cette étape fait appel à ce que l’on a appris dans les cours Création de fonctions en R et Tests et exceptions
en R.
Lorsque l’on crée des fonctions dans le but de les inclure dans un package, il faut garder en tête le chemin
de recherche complet qu’utilisera R lors de l’exécution de ces fonctions (voir ci-dessus). Dans ce chemin de
recherche, on ne peut pas se fier au contenu de l’environnement de travail, car il varie constamment en cours
de session. On ne peut pas non plus se fier aux packages chargés. En effet, la liste des packages chargés varie
aussi en cours de session et d’un utilisateur à l’autre.
Ainsi, dans le corps des fonctions d’un package, on peut faire appel à des variables locales, à d’autres objets
dans le package (publiques ou privés) et à des objets du package R de base, qui est toujours inclus dans le
chemin de recherche. Si on souhaite faire appel à des objets autres, par exemple des fonctions provenant
d’autres packages, il faudra faire le nécessaire pour inclure ces fonctions dans l’environnement des objets
importés par le package.
Aussi, si notre but est éventuellement de rendre notre package public sur le CRAN, il faut respecter les
politiques du CRAN : http://cran.r-project.org/web/packages/policies.html. La plus importante de ces
politiques est que notre package doit passer le R CMD check --as-cran sans erreurs ni avertissements (on
en reparle plus loin). Pour passer cette vérification sans problèmes, notre code ne doit pas, entre autres :
8
• contenir des symboles non-ASCII (donc pas d’accents, même dans nos commentaires),
• utiliser d’association partielle d’argument (donc on doit s’assurer d’utiliser le nom complet des arguments
dans les appels de fonction),
• toujours utiliser comme valeurs logiques TRUE ou FALSE (donc pas de T ou F).
Étape 2. Créer la bonne structure de fichiers
Un package dans sa version source est simplement un répertoire de fichiers compressés. Cependant, ce
répertoire doit comprendre des fichiers et des sous-répertoires portant des noms précis.
On peut créer cette structure de fichiers à l’aide de la fonction package.skeleton. Cependant, on peut aussi
créer manuellement les dossiers et fichiers. Il faut d’abord créer un dossier portant le nom du package. Voici
ce que doit contenir obligatoirement ce dossier.
Dossier nommé “R”
Ce dossier doit comprendre des fichiers de scripts R (portant l’extension .R) contenant le code de création des
fonctions ainsi que les commentaires roxygen2 si c’est l’outil que l’on utilise pour générer la documentation
(on y revient plus loin). Le développeur peut choisir les noms qu’il veut pour ces fichiers et il peut y répartir
le code source comme il le veut. Évidemment, une bonne pratique est de répartir le code source de façon à ce
que ce soit facile de s’y retrouver.
Dossier nommé “man”
Ce dossier doit comprendre des fichiers sources de fiches d’aide R (portant l’extension .Rd). On va voir à la
prochaine étape comment écrire ces fichiers.
Fichier nommé “DESCRIPTION”
Il s’agit d’un fichier très important pour la compilation du package. C’est un fichier court, comportant de
l’information de base sur le package. Cependant, ce fichier doit respecter une syntaxe précise.
Référence officielle concernant ce fichier :
http://cran.r-project.org/doc/manuals/r-release/R-exts.html#The-DESCRIPTION-file
Exemple :
Package: monpkg
Type: Package
Title: Distance de Manhattan
Version: 1.0
Date: 2015-03-26
Author: Sophie Baillargeon
Maintainer: Sophie Baillargeon <[email protected]>
Description: Calcul de la distance de Manhattan entre deux points.
License: GPL-3
Fichier nommé “NAMESPACE”
C’est un fichier qui permet de définir quels objets sont accessibles dans un package, c’est-à-dire exportés
de l’espace de noms du package. Ce fichier permet aussi d’identifier quelles fonctions provenant d’autres
packages sont utilisées dans le package, donc de définir le contenu de l’environnement des objets importés par
le package. On va voir plus loin comment utiliser roxygen2 pour écrire correctement ce fichier.
9
Autres fichiers et dossiers
Un package peut contenir plusieurs autres fichiers et dossiers. Cependant, ces derniers ne sont pas obligatoires.
Autres dossiers parfois nécessaires :
• Dossier nommé “data” : Si le package contient des jeux de données, ils doivent se trouver dans ce
dossier.
• Dossier nommé “src” : Si le package contient du code C, C++ ou Fortran, il doit se trouver dans ce
dossier.
• Dossier nommé “inst” : Si le package contient de la documentation autre que les fiches d’aide (par
exemple un guide d’utilisateur appelé vignette), il doit se trouver dans ce dossier.
• etc. : http://cran.r-project.org/doc/manuals/r-release/R-exts.html#Package-subdirectories
Autres fichiers que l’on souhaite parfois ajouter :
• Fichier nommé “NEWS” : Ce fichier décrit les modifications apportées à un package lors d’une mise à
jour. Sa mise en forme n’est pas vraiment importante.
• etc. : http://cran.r-project.org/doc/manuals/r-release/R-exts.html#Package-structure
Étape 3. Écrire la Documentation des fonctions et du package
Documenter ses fonctions est en fait une étape intégrée au développement des fonctions. Cependant, il faut
maintenant écrire la documentation dans un format qui générera correctement les fiches d’aide qui doivent
être incluses dans le package.
Ces fiches d’aide proviennent en fait de fichiers portant l’extension .Rd. Cependant, on ne verra pas comment
éditer directement ces fichiers. On va plutôt apprendre à faire ça en utilisant roxygen2. Le package roxygen2
est un outil qui permet de générer des fichiers .Rd ainsi que le fichier NAMESAPCE de façon automatique, à
partir de commentaires intégrés au code.
Rapellons que dans un package il faut documenter :
- les fonctions publiques Il est essentiel de faire des fiches d’aide pour ces fonctions, afin que tout utilisateur
comprenne comment appeler correctement la fonction. Si un utilisateur a mal compris la documentation
et fourni par erreur une valeur d’argument invalide en entrée, il est souhaitable que la fonction retourne
une erreur informative. Le code de ces fonctions publiques comporte donc typiquement de la validation des
arguments fournis en entrée.
À l’opposé, les fonctions privées ou internes ne sont pas conçues pour être appelées par n’importe quel
utilisateur. On cache donc ces fonctions en ne les exportant pas d l’espace de noms et en ne les documentant
pas officiellement. Il est tout de même bon de documenter minimalement ces fonctions pour nous-mêmes,
mais on n’a pas à produire de fiches d’aide pour elles. Pour ne pas alourdir ces fonctions, on valide leurs
arguments uniquement si on ne peut pas contrôler les valeurs fournies en entrée.
- les méthodes pour des fonctions génériques On peut leur faire une fiche d’aide indépendante ou
encore les documenter dans la même fiche d’aide que la fonction qui crée les objets de la classe en question.
- les jeux de données Chaque jeu de données dans un package devrait être décrit dans une fiche d’aide
pour expliquer son contenu.
- le package lui-même On doit créer une fiche d’aide présentant le package.
10
Comment écrire de la documentation avec roxygen2?
Exemples :
D’abord, voici des exemples de scripts R contenant des commentaires roxygen2. Des explications se retrouvent
après les exemples.
Fichier ./R/Manhattan.R :
#' Distance de Manhattan
#'
#' Calcule la distance de Manhattan entre deux points
#'
#' @param pt1 Un vecteur numerique des coordonnees du premier point.
#' @param pt2 Un vecteur numerique des coordonnees du deuxieme point.
#'
#' @return une seule valeur : la distance de Manhattan entre
#'
\code{pt1} et \code{pt2}
#'
#' @author Sophie Baillargeon
#'
#' @export
#'
#' @examples
#' Manhattan(pt1 = c(0,-5), pt2 = c(0,-15))
Manhattan <function(pt1, pt2) {
# Validation des arguments
if (length(pt1) != length(pt2))
stop("'pt1' and 'pt2' must have the same length")
if (!is.null(dim(pt1)) || !is.null(dim(pt2)))
warning("'pt1' and 'pt2' are treated as dimension 1 vectors")
# Calculs
sum(abs(pt1 - pt2))
}
Fichier ./R/Manhattan2.R :
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
#'
Distance de Manhattan
Calcule la distance de Manhattan entre deux points
Utilise la fonction \code{\link{dist}} du package \pkg{stats}.
@param pt1 Un vecteur numerique des coordonnees du premier point.
@param pt2 Un vecteur numerique des coordonnees du deuxieme point.
@return \item{dist}{ la distance de Manhattan entre \code{pt1} et \code{pt2} }
@return \item{call}{ une copie de l'appel de la fonction }
@author Sophie Baillargeon
@export
@importFrom stats dist
11
#' @examples
#' Manhattan2(pt1 = c(0,-5), pt2 = c(0,-15))
Manhattan2 <- function(pt1, pt2) {
call <- match.call()
dist <- dist(rbind(pt1, pt2), method = "manhattan")
list(dist = as.vector(dist), call = call)
}
Fichier ./R/print.Manhattan.R :
#' @rdname Manhattan
#' @method print Manhattan
#' @param x Un objet produit par la fonction \code{Manhattan}, a afficher.
#' @param \dots D'autres arguments passea a d'autres methodes.
#' @export
print.Manhattan <function(x, ...) {
cat("Manhattan distance between 'pt1' and 'pt2' :", x$dist)
invisible(x)
}
Fichier ./R/monpkg.R :
#' Distance de Manhattan
#'
#' Distance de Manhattan entre deux points
#'
#' \tabular{ll}{
#' Package: \tab monpkg\cr
#' Type: \tab Package\cr
#' Version: \tab 1.0\cr
#' Date: \tab 2015-03-26\cr
#' License: \tab GPL-3\cr
#' }
#'
#' @name monpkg-package
#' @aliases monpkg-package monpkg
#' @docType package
#' @author Sophie Baillargeon
#'
#' Maintainer: Sophie Baillargeon <sophie.baillargeon@@mat.ulaval.ca>
#' @keywords package
NULL
#'
#'
#'
#'
#'
#'
#'
#'
Points aleatoires
Coordonnes en deux dimensions de 10 points aleatoires.
@name points
@docType data
@format Une matrice contenant 10 points designes par les
coordonnees suivantes.
12
#' \describe{
#'
\item{X}{ coordonnee en X }
#'
\item{Y}{ coordonnee en Y }
#' }
#' @keywords datasets
#' @examples
#' data(points)
#' Manhattan(pt1 = points[4, ], pt2 = points[8, ])
NULL
Explications :
Un commentaire roxygen2 doit débuter par le symbole #'.
Pour les fonctions et les méthodes pour des fonctions génériques, il suffit de mettre en entête au code source
les commentaires roxygen2 qui généreront la documentation. Pour le package et les jeux de données, on
ajoute un fichier dans le dossier “R”. On met dans ce fichier .R les commentaires roxygen2 pour chaque fiche
d’aide, tous suivis d’une ligne avec le code :
NULL
La première phrase de ces commentaires doit être le titre de la fiche d’aide.
Cette phrase doit être suivie d’une ligne vide, puis du texte à mettre dans la section Description.
Si on souhaite avoir une section Details, il faut mettre à la suite de ce texte une ligne vide. Tout le texte
après cette ligne vide, mais avant les lignes débutant par un tag roxygen2 formera la section Details.
On insère ensuite toutes les lignes débutant par des tags. Il faut obligatoirement décrire :
• les paramètres en entrée avec le tag @param et
• la sortie avec le tag @return.
Il est aussi essentiel de mettre les tags pour l’écriture du NAMESPACE :
• le tag @export exporte une fonction du NAMESPACE (donc la rend publique),
• le tag @importFrom assure l’importation des fonctions provenant d’autres packages qui sont utilisées
dans le code de notre package.
On peut ajouter les informations suivantes :
•
•
•
•
les noms des auteurs avec le tag @author,
des références avec le tag @references,
des liens vers les fiches d’aide de fonction en lien avec la fonction documentée avec le tag @seealso,
etc. : voir les vignettes du package roxygen2 http://CRAN.R-project.org/package=roxygen2.
Les méthodes doivent être déclarées avec le tag @method.
Si on veut jumeler des fiches d’aide, on a besoin du tag @rdname.
On peut contrôler le nom de la fiche d’aide avec le tag @name. Sans ce tag, la fiche d’aide porte le nom de la
fonction qui suit le bloc de documentation roxygen2. Pour une documentation de package ou d’un jeu de
données, c’est la ligne de code NULL qui suit le bloc de documentation. Il faut donc obligatoirement dans ce
cas un tag @name. Dans ce cas, il faut aussi spécifier le type de documentation avec le tag @docType.
13
Il est recommandé de toujours mettre des exemples dans une fiche d’aide. Dans la documentation roxygen2,
ceux-ci doivent être ajoutés à la fin du bloc de documentation, après le tag @examples.
Dans les commentaires roxygen2, les tags de mises en forme recommandés dans les fichiers .Rd (par exemple
\code{}, \pkg{}, \item{}, \link{}, \dots, etc. http://cran.r-project.org/doc/manuals/r-release/R-exts.
html#Marking-text) devraient toujours être employés.
Comment générer les fichiers .Rd et le fichier NAMESPACE ?
Il suffit de lancer la commande roxygenize du package roxygen2. On peut le faire directement dans la
console, ou encore par le menu de RStudio (voir prochaine section).
Étape 4. Compiler et vérifier le package
Cette étape se réalise avec les commandes :
• R CMD check,
• R CMD build,
• R CMD INSTALL.
Ces commandes ne sont pas lancées dans la console R. Elles sont lancées dans le terminal sous Linux ou OS
X (Mac) et dans une fenêtre invite de commandes sous Windows.
Il faut avoir les bons outils sur son ordinateur (voir le guide d’installation ou de mise à jour de R et RStudio) :
• R,
• Rtools,
• compilateur LaTeX si on veut générer la documentation en PDF.
RStudio peut lancer pour nous les commandes de compilation et de vérification. Le logiciel rend le processus
vraiment plus simple que de lancer les commandes manuellement dans le terminal ou l’invite de commandes.
On apprendra donc seulement comment compiler et vérifier un package avec RStudio
Sous-étape a) Créer un projet RStudio avec notre package
•
•
•
•
Par le menu File -> New Project. . . ,
sélectionner Existing Directory,
sélectionner le dossier portant le nom du package et contennant les fichiers source,
cliquer sur Create Project.
Le projet sera créé et ouvert. Ça ajoute des fichiers dans le dossier de notre package. On ne se préoccupera
pas de ces fichiers. Ils seront automatiquement ignorés lors de la compilation du package avec RStudio.
Sous-étape b) Configurer les options de RStudio
Options globales (à faire une seule fois) :
• par le menu Tools -> Global Options. . . ,
• dans Packages, décocher Cleanup output after successful R CMD check.
14
Options du projet (à faire pour chaque nouveau projet) :
• par le menu Tools -> Project Options. . . ;
• sans Build Tools :
– cocher Generate Documentation with Roxygen,
– cliquez sur Configure, puis cocher : NAMESPACE file;
• si vous n’avez pas de compilateur LaTeX sur votre ordinateur, ajoutez l’option suivante à R CMD check
: –no-manual.
Sous-étape c) Compiler à partir du menu Build de RStudio
Il est préférable de toujours d’abord s’assurer que le package passe sans erreur ou avertissements problématiques
la vérification faite par la commande R CMD check. Ensuite, on peut compiler le package, soit dans sa version
source ou binaire .
• Pour créer le package source (qui est aussi la version Linux/Unix) :
menu Build -> Build Source Package.
• Pour vérifier le package :
menu Build -> Check Package.
• Pour créer le package binaire (pour Windows) :
menu Build -> Build Binary Package
La compilation Build ans Reload est pratique en cours de travail. Elle permet de compiler le package dans
le bon format pour notre système d’exploitation, l’installer (donc remplacer l’ancienne installation par la
nouvelle) et charger de nouveau le package (avec la commande library).
Étape 5. Au besoin, mettre à jour le package
Lors d’une mise à jour de notre package, il faut :
Sous-étape a) Incrémenter le numéro de version dans le fichier DESCRIPTION ainsi que dans la
fiche d’aide du package.
Sous-étape b) Faire les mises à jour dans le code
Sous-étape c) Documenter les modifications dans les commentaires roxygen2 produisant les fiches
d’aide ainsi que dans le fichier NEWS.
Sous-étape d) Recompiler le package
15
Références
• R Core Team (2015). Writing R Extensions. R Foundation for Statistical Computing. Chapitre 4.
http://cran.r-project.org/doc/manuals/r-release/R-exts.pdf
• Wickham, H. (2015). R packages. O’Reilly, à paraître. http://r-pkgs.had.co.nz/tests.html
• Wickham, H., Danenberg, P., and Eugster, M. (2014). roxygen2: In-source documentation for R. R
package version 4.1.0. http://CRAN.R-project.org/package=roxygen2
Accéder au code source :
• Ligges, U. (2006). R Help Desk: Accessing the Sources. R News, vol. 6, no. 4, p. 43-45. http:
//cran.r-project.org/doc/Rnews/Rnews_2006-4.pdf
16