Create A Package Skeleton

Peter DeWitt

The create_pkg, and its sister functions create_data_raw and create_vignette, are provided to build a package skeleton that I prefer. These functions are based on the devtools create, use_vignette and use_data_raw functions.

This vignette will provided a detailed explanation of the package structure and design I prefer for R package development.

This vignette only needs the qwraps2 namespace loaded and attached.

library(qwraps2)

Section 1: create_pkg

The basic package skeleton is created with the create_pkg function.

str(create_pkg)
## function (path, use_data_raw = FALSE, ci = NULL, rstudio = FALSE, 
##     ...)

The path is a directory to use for the package. For the examples to follow we will use a temporary directory.

tmp_dir <- tempdir()
pkg_dir <- paste(tmp_dir, "eg.pkg", sep = "/")
pkg_dir
## [1] "/var/folders/76/c_58hkfs13g3rn64v707fdxh0000gp/T//RtmpNuKUOh/eg.pkg"
create_pkg(pkg_dir)
## Warning in normalizePath(path.expand(path)): path[1]="/var/folders/76/
## c_58hkfs13g3rn64v707fdxh0000gp/T//RtmpNuKUOh/eg.pkg": No such file or
## directory

Let’s look at the files and the skeleton created for the package. We’ll do this a few times so a tree function will be created and used:

tree <- function(pkg_dir) {
  files <- list.files(pkg_dir,
                      all.files = TRUE,
                      full.names = TRUE,
                      recursive = TRUE,
                      include.dirs = TRUE)
  files <- data.frame(filename = gsub(tmp_dir, "", files), file.info(files)) 
  print(data.tree::as.Node(files, pathName = "filename"), "isdir")
}
tree(pkg_dir)
##              levelName isdir
## 1  eg.pkg                 NA
## 2   ¦--.Rbuildignore   FALSE
## 3   ¦--.gitignore      FALSE
## 4   ¦--CONTRIBUTING.md FALSE
## 5   ¦--DESCRIPTION     FALSE
## 6   ¦--NAMESPACE       FALSE
## 7   ¦--NEWS.md         FALSE
## 8   ¦--R                TRUE
## 9   ¦--README.md       FALSE
## 10  ¦--examples         TRUE
## 11  °--makefile        FALSE

There are two empty directories created, the R directory and the examples directory. The examples directory is expected to be used to store the examples for the documentation written, using roxygen2 markup, in the files within the R directory. More details are given in a later section.

The files populating the root directory of the package includes the needed DESCRIPTION file, which you, the package developer, will need to edit. Details on the metadata and what/how to edit it is found in the R packages book by Hadley Wickham.

cat(readLines(paste0(pkg_dir, "/DESCRIPTION")), sep = "\n")
## Package: eg.pkg
## Title: What the Package Does (one line, title case)
## Version: 0.0.0.9000
## Authors@R: person("First", "Last", email = "first.last@example.com", role = c("aut", "cre"))
## Description: What the package does (one paragraph).
## License: What license is it under?
## Encoding: UTF-8
## LazyData: true
## VignetteBuilder: knitr

The NAMESPACE file is provided, but should not be edited by the end user, let devtools::document(), called via the makefile handle the edits to the NAMESPACE file. General package documentation in the form of a README.md, CONTRIBUTING.md, and NEWS.md are provided. The .Rbuildignore and .gitignore files are provided with commonly needed expressions. Lastly, the makefile is provided for building, checking, and installing the package. A help recipe has been provided in the makefile.

make help

The recipes in the makefile are:

# cat(readLines(paste0(pkg_dir, "/makefile")), sep = "\n")

This makefile is built to be useful for most R package development, it is copied into new R packages created by qwraps2::create_pkg, see vignette("create_pkg", package = "qwraps2").

usage: make [build-options] [check-options] [install-options] [targets]

Target Description
all Build the man files, vignettes, and the <package>_<version>.tar.gz file
help Display usage, targets, and options provided by the makefile
check Run R CMD check
install Install the R package via R CMD INSTALL
document Construct raw data sets, if needed, and build/update man files.
vignettes
Options Description
build-options

If the rstudio option is used when calling create_pkg then a .Rproj file is added to the root directory.

The ci argument is used to add template files for either Travis CI or gitlab runners.

The use_data_raw option is used if raw data is to be part of the package. calling the create_data_raw function can be called later to create the directories and place the generic makefiles as needed to work with the makefile in the package root directory.

create_data_raw

Adding the data-raw and data directories to the package, if not done on the initial construction, is done via

The updated package structure is:

The makefile in the data-raw is generic such that any .R file will be evaluated. Noting that some scripts needed to create a data set might require a non-trivial amount of time to evaluate, the makefile creates, and then uses, md5sums for assessing if the .R file(s) needs to be re-evaluated instead of the standard file modified time stamp.

create_vignette

Authoring vignettes is a great way to document your package. I have found that the parallel development of a ‘how to use this package’ vignette while writing and testing the package code has made development and documentation easier.

Developing the vignette and the code base can be painful. Consider a standard .Rmd or .Rnw file with with R code in individual chunks. Having to re-evaluate all the chunks can be time consuming and cumbersome depending on your IDE. An alternative method is to author .R files with the expectation of using knitr::spin to generate the .Rmd file that then gets processed into the vignette(s).

The create_vignette places a template vignette file and makefile into a vignettes directory.#’

It is critically important that you do not use devtools::build_vignettes() as this will over write the .R file. If you need to build the vignettes without building the whole package use the makefile in the package root directory and call

make .vignettes.Rout

Examples:

The best example for this style of package development is the qwraps2 package on github.

Session Info

print(sessionInfo(), local = FALSE)
## R version 3.4.4 (2018-03-15)
## Platform: x86_64-apple-darwin17.3.0 (64-bit)
## Running under: macOS High Sierra 10.13.4
## 
## Matrix products: default
## BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
## LAPACK: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] qwraps2_0.3.0 knitr_1.20   
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.16       plyr_1.8.4         compiler_3.4.4    
##  [4] pillar_1.2.1       RColorBrewer_1.1-2 influenceR_0.1.0  
##  [7] bindr_0.1.1        viridis_0.5.1      tools_3.4.4       
## [10] digest_0.6.15      jsonlite_1.5       viridisLite_0.3.0 
## [13] gtable_0.2.0       evaluate_0.10.1    memoise_1.1.0     
## [16] tibble_1.4.2       rgexf_0.15.3       pkgconfig_2.0.1   
## [19] rlang_0.2.0.9001   igraph_1.2.1       rstudioapi_0.7    
## [22] yaml_2.1.18        bindrcpp_0.2.2     gridExtra_2.3     
## [25] downloader_0.4     withr_2.1.2        DiagrammeR_1.0.0  
## [28] dplyr_0.7.4        stringr_1.3.0      htmlwidgets_1.0   
## [31] devtools_1.13.5    hms_0.4.2          grid_3.4.4        
## [34] rprojroot_1.3-2    data.tree_0.7.5    glue_1.2.0        
## [37] R6_2.2.2           Rook_1.1-1         XML_3.98-1.10     
## [40] rmarkdown_1.9      ggplot2_2.2.1.9000 tidyr_0.8.0       
## [43] purrr_0.2.4        readr_1.1.1        magrittr_1.5      
## [46] backports_1.1.2    scales_0.5.0.9000  htmltools_0.3.6   
## [49] assertthat_0.2.0   colorspace_1.3-2   brew_1.0-6        
## [52] stringi_1.1.7      visNetwork_2.0.3   lazyeval_0.2.1    
## [55] munsell_0.4.3