Dans une démarche de recherche reproductible nous souhaitons créer un package qui permettra de diffuser et de reproduire une analyse. Ce package contiendra les données utilisées et leur documentation, les fonctions utilisées et leur documentation ainsi que l’analyse elle-même.
Le package est la forme naturel de partage dans l’environnement R.
Il est possible de créer un package sans logiciel particulier (notepad++, gedit…) mais grâce à plusieurs outils l’environnement de développement RStudio facilite grandement le processus.
Nous verrons ici comment construire un package avec RStudio, comment y ajouter des données et comment insérer également les analyses sous forme de vignettes.
La structure des packages R est assez simple. Dans le dossier d’un package il faut obligatoirement :
/R
contenant les fichiers .R
avec les fonctions.NAMESPACE
.DESCRIPTION
décrivant brièvement quelques éléments du package.Et l’on peut rajouter :
/data
contenant les données au format RData
ou autre./vignettes
pouvant contenir des documents Rmd
(RMarkdown) qui généreront des documents .pdf
ou .hmtl
combinant textes, analyses et code R.devtools
est utile pour compiler et construire les packages Rroxygen2
est permet de documenter les fonctions d’un package directement et facilement dans le code et non dans des fichiers séparés d’un formalisme lourd.Aller dans Build > Configure Build Tools et choisir package
Dans la fenêtre qui s’ouvre cliquer sur Generate documentation with Roxygen puis sur Configure et sélectionner toutes les options.
Notons qu’un onglet Build s’est rajouter dans l’environnement RStudio.
/R
et un fichier .R
Le dossier du package doit contenir un sous-dossier /R
.
Ce dossier contiendra au moins un fichier .R
contenant les fonctions du package.
Dans cet exemple nous créons une fonction qui élève au carré un nombre.
Et nous enregistrons la fonction dans un fichier nommé mesFonctions.R
.
Les commandes suivantes génèrent automatiquement le fichier DESCRIPTION
qui décrit le package succinctement.
library(roxygen2)
library(devtools)
load_all()
Le fichier DESCRIPTION
vient d’être créé.
Il faut le modifier un peu pour l’adapter au contenu réel du package.
Nous avons rajouter les champs Maintainer
et Encoding
(UTF-8 car le nom de l’auteur contient un accent).
Lancer load_all()
à nouveau permet de voir si le fichier est correctement formé.
Nous pouvons maintenant lancer la construction du package en appuyant sur le bouton Build & Reload.
Le package est maintenant présent et démarré dans la liste des packages.
Il ne contient en revanche aucune documentation.
Nous pouvons maintenant documenter les fonctions que nous avons créées et empaquetées.
Cette documentation est écrite avec les “commentaires” roxygen
.
Ces commentaires sont écrits directement dans le fichier des fonctions.
Toutes les lignes commencent par #'
.
@param
indiquent les arguments de la fonction@return
indique ce que renvoie la fonction@export
permet de rendre la fonction visible dans l’environnement R
Lorsque l’on relance Build & Reload la documentation est bien créée :
Il est préférable de créer également une entrée de documentation générale sur le package à laquelle on accédera par :
?monPackage
On peut le faire en entrant les lignes suivantes dans le fichier mesFonctions.R
:
Une fois la documentation correctement renseignée il faut construire le package pour permettre sa diffusion.
Pour cela nous allons d’abord le vérifier en appuyant sur le bouton Check Package. Si nous n’obtenons pas de Warnings nous pouvons enfin le construire en appuyant sur le bouton Build Source Package.
Un message de ce type doit s’afficher :
Nous venons de créer le fichier monPackage_0.1.tar.gz
. Pour installer le package sur une autre machine il faudra lancer l’instruction suivante :
install.packages("chemin_du_fichier/monPackage_0.1.tar.gz", repos = NULL, type = "source")
Les données que nous utilisons fréquemment dans nos analyses sont la plupart du temps stockées sous forme de fichier texte (.csv, .txt) ou au pire dans des fichier excel. En géographie nous utilisons également des fichiers spatiaux (shapefiles…).
L’utilisation de ces fichiers implique systématiquement un processus d’importation dans les scripts (read.csv()
, readShapeSpatial()
etc.) qui nécessite de connaitre la manière dont le fichier est formaté.
R possède un format spécifique des données, le format RData
. Ce format a l’avantage de stocker directement des objets R (data.frame
, vector
, SpatialPolygonsDataFrame
…) dans un fichier. Il est ensuite facile de documenter les objets stockés.
Créons d’abord pour l’exemple deux data.frame
:
monDf <- data.frame(id = c("a", "b", "c", "d", "e"), maVariable = c(1,3,2,4,6))
tonDf <- data.frame(id = c("a", "b", "c", "d", "e"), maVariable = c(5,3,1,0,100))
Si nous souhaitons insérer ces jeux de données dans le package monPackage il faut les enregistrer au format RData
dans un sous dossier /data
dans le dossier du package.
dir.create("/mnt/data/monPackage/data/")
save(monDf, tonDf, file = "/mnt/data/monPackage/data/mesData.RData")
Lorsque l’on créé à nouveau les sources du packages les données sont alors disponibles.
La fonction data()
permet d’importer des jeux de données dans l’environnement.
library(monPackage)
data(mesData)
monDf$maVariableAuCarre <- square(monDf$maVariable)
monDf
## id maVariable maVariableAuCarre
## 1 a 1 1
## 2 b 3 9
## 3 c 2 4
## 4 d 4 16
## 5 e 6 36
Ces données ne sont en revanche pas documentées. Nous pouvons créer leur documentation dans le fichier mesFonctions.R
:
@name
doit se référer au nom de l’objet@field
peut donner des indications sur les colonnes d’un data.frame
@docType
indique que nous sommes en train de documenter des donnéesNULL
Ce qui donnera ceci pour monDf
:
Le fichier mesFonctions.R
complet :
#' Le Nom de la Fonction
#'
#' La description de la fonction (Description)
#'
#' Les details de de la fonction (Details)
#' @param x Les paramètres de la fonction. Ne pas oulier les valeurs par défaut,
#' le type d'objet, le caractère obligatoire du champs... (Arguments)
#' @return Ce que la fonction renvoie (Value)
#' @export
square <- function(x){
return(x^2)
}
#' monPackage
#'
#' Voila donc mon package. Vous trouverez tel
#' genre de fonction dedans...
#'
#' @name monPackage
#' @docType package
NULL
#' monDf
#'
#' Ceci est mon dataframe
#' @name monDf
#' @field id ce champ est d'identifiant
#' @field maVariable ce champ est ma variable
#' @docType data
#' @keywords data
NULL
#' tonDf
#'
#' Ceci est ton dataframe
#' @name tonDf
#' @docType data
#' @keywords data
NULL
Grace aux vignettes et au R Markdown nous pouvons très facilement publier des analyses au sein du package.
Il faut d’abord créer un dossier /vignettes
dans le dossier du package et y créer un document R Markdown (.Rmd
).
Puis ajouter les lignes suivantes au début du document (après les champs de métadonnées titre author etc.) :
<!--
%\VignetteEngine{knitr::knitr}
%\VignetteIndexEntry{Utilisation de monPackage}
-->
Dans le fichier DESCRIPTION
il faut ajouter les éléments suivants :
VignetteBuilder: knitr
Ici nous avons ajouter le fichier Utiliser_la_fonction_square.Rmd
au dossier /vignettes
:
Une fois le package installé la commande suivante ouvrira la vignette dans le navigateur :
vignette("Utiliser_la_fonction_square", package = "monPackage")
Cette présentation vise surtout à présenter les grands principes de la création de package. Pour aller plus loin, par exemple pour déposer un package sur le CRAN qui vérifie strictement la forme des packages déposés, vous pourrez vous référer à la documentation riche disponible sur le web. Suivent quelques références :