Tue 16 Feb 2016 — Sat 21 Sep 2019

R Packages

Notes on the structure of R packages and how to create them, based on R Packages by Hadley Wickham.

help(package = 'my-lovely-package') gives you a basic overview of what's in the package.

Directory structure:

  • R/ (code)
  • tests/
  • data/
  • DESCRIPTION is some metadata: name, version, dependencies
  • NAMESPACE

The devtools package will set this up for you.

Bundled packages include HTML and PDF outputs, but not temporary artifacts or anything matched by the contents of .Rbuildignore. They're zipped up.

Turn functions into binary code by calling save().

.libPaths() shows loaded libraries.

Code

Packages are run when they're built. They export packages (objects containing functions) at this time.

.onLoad() and .onAttach() can do some setup work for packages.

You can also write .Deprecated("thing-to-use-instead")

Metadata

Uses Debian control format.

  • Title
  • Version
  • Description
  • Imports
  • Suggests
  • Collate (if your code has side-effects)
  • LazyData (hmm)

Documentation

This is your library documentation. Use roxygen2.

#' means this comment line is roxygen documentation.

You can include various tags.

You can also incorporate LaTeX.

#' My lovely function
#' Which does this
#' \code{f}
#' \link{some link}
#'
#' @section My section:
#' blah blah blah
#'
#' @aliases g h i
#' @keywords internal
#'
#' @param x A number.
#' @return What it returns.
#' @examples
#' f(x + y)

To put high level documentation on your package, put some documentation on NULL:

#' About my package.
#' @docType package
#' @name package-name
NULL

Vignettes

Use R markdown, with some yaml at the top for good measure.

You can use knitr::table() to output tables.

Some people like to do little bits of analysis as packages. You walk the person through your thinking in the vignette, and the rest of the package is helper and support code. See: http://rmflight.github.io/posts/2014/07/analyses_as_packages.html

Tests

Put testthat as a suggested package.

skip() lets you skip tests.

context("type of test") lets you describe the tests in your file

Use bquote, substitute etc. when making helper functions to avoid having to pass in so much documentation.

Namespaces

Write a NAMESPACE file.

It contains export(), exportClasses() and importFrom() calls (and others…).

roxygen2 + devtools will make this file for us using devtools::document().

Write this on an R thing to mark it for export:

#' @export

It's probably easiest to not include imports in the NAMESPACE file, and instead use all imports full qualified as package::fun().

Data

Binary

Binary data goes in data/. Make the files in here by calling save() on R objects (or devtools::use_data()).

You can put other data here, but .RData files are a good choice.

LazyData: true in the DESCRIPTION file is important here.

Data is automatically exported.

You should document your datasets with @format and @source.

Binary Internal

Again, we use devtools::use_data(), but with the internal = TRUE argument. It ends up in R/sysdata.rda.

Text / Raw

Text data goes in inst/extdata

Load it using system.file().

Compiled Code

Rcpp is what you'd use to write C++ for R.

The result goes in the src/ directory.

Remember to unload the C code when your package is unloaded.

Use Clang instead of gcc for better error messages.

High Performance Functions with Rcpp

Portable C++ for R Packages

You can also interoperate with Java using rJava, or Fortran. Good luck!

Plain C

You can use .C() to call any C function, and .Call() to call one that you have defined an R interface for.

You need to use the SEXP type everywhere.

Installed Files

Things in the /inst directory get copied into the top level directory when the package is installed. Files here can be accessed using system.file().