Introduction to R Package Development 2019

blog
r-package
Author

Stephanie Hicks

Published

May 20, 2019

Motivation

In this tutorial, you are going to create your own package using the usethis workflow R package. For our purposes, we are using the code provide on the usethis website and the blog from Emil Hvitfeldt.

This package is great because it automates repetitive tasks that arise during project setup and development, both for R packages and non-package projects.

Getting started with the usethis package

Installation

Install the released version of usethis from CRAN:

install.packages("usethis")

Or install the development version from GitHub with:

# install.packages("devtools")
devtools::install_github("r-lib/usethis")

You may also need these packages:

install.packages("testthat")
install.packages("spelling")

Creating your R package using usethis

Most use_*() functions operate on the active project: literally, a directory on your computer. If you have just used usethis to create a new package or project, that will be the active project. Otherwise, usethis verifies that current working directory is or is below a valid project directory and that becomes the active project.

A few usethis functions have no strong connections to projects and will expect you to provide a path.

Below is a quick look at how usethis can help to set up a package. But remember, many usethis functions are also applicable to analytical projects that are not packages.

Let’s load the library

library(usethis)

Next we create a path to a temporary folder and call the package mypkg.

path <- file.path(tempdir(), "mypkg")
path
[1] "/var/folders/7r/39cms9lx3rncwj6f5myx2fz40000gn/T//RtmpKhDIkN/mypkg"

Then, we use the create_package() function to create the skeleton of this package.

Create the package

create_package(path)
✔ Creating '/var/folders/7r/39cms9lx3rncwj6f5myx2fz40000gn/T/RtmpKhDIkN/mypkg/'
✔ Setting active project to '/private/var/folders/7r/39cms9lx3rncwj6f5myx2fz40000gn/T/RtmpKhDIkN/mypkg'
✔ Creating 'R/'
✔ Writing 'DESCRIPTION'
Package: mypkg
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R (parsed):
    * First Last <first.last@example.com> [aut, cre] (YOUR-ORCID-ID)
Description: What the package does (one paragraph).
License: `use_mit_license()`, `use_gpl3_license()` or friends to pick a
    license
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
✔ Writing 'NAMESPACE'
✔ Setting active project to '<no active project>'

If you are inside of RStudio, this will (hopefully) open up a new RStudio session. Also, usethis is quite chatty, explaining what it’s doing and assigning you tasks. For example,

✔ indicates something usethis has done for you.

● indicates that you’ll need to do some work yourself.

For this tutorial, we are not in an interactive session. So we use the proj_activate(path) function with the path argument to change the working directory to the temporary path that we’ve created.

NOTE: You only need to run proj_activate(path) if you are not in an interactive session.

proj_activate(path)
✔ Setting active project to '/private/var/folders/7r/39cms9lx3rncwj6f5myx2fz40000gn/T/RtmpKhDIkN/mypkg'
✔ Changing working directory to '/var/folders/7r/39cms9lx3rncwj6f5myx2fz40000gn/T/RtmpKhDIkN/mypkg/'

Setting up git/github

We won’t do it here, but you can use the functions below to help set link the pakckage to GitHub. If you want to explore this, check out Jenny Bryan tutorial on getting setup.

use_git()
use_github()

One time modifications

Now that we are up and running there is a bunch of things we should do before we start writing code. Firstly we will go over all the actions that only have to be done once and get those out of the way.

Setting up your license

There are several types of licenses you can pick from, for example

use_mit_license()
use_gpl3_license()
use_apl2_license()
use_cc0_license()

Let’s select the MIT license

use_mit_license("Margaret Taub")
✔ Adding 'MIT + file LICENSE' to License
✔ Writing 'LICENSE'
✔ Writing 'LICENSE.md'
✔ Adding '^LICENSE\\.md$' to '.Rbuildignore'

The choice of license is beyond the scope of the tutorial, but we refer readers here to learn more about types of licenses.

Add README.md files

Now we add the readme files, this is done using the use_news_md() function. This will create a readme.md file that you can edit and knit as you normally would.

use_news_md()
✔ Writing 'NEWS.md'

Adding continuous integration (optional)

Next we will setup some continuous integration. This is completely optional, but it’s recommended. A nice intro to this topic is from Julia Silge.

For a quick summary, we will extract a section from her blog post:

“If you have written an R package, you probably have gotten into the habit of running R CMD check on a (hopefully) regular basis to check for common problems. It automatically detects lots of problems that can arise that you might not otherwise notice. Also you probably have put your package on GitHub, for version control and also to be able to share your code with other people and track issues and whatnot. The idea behind continuous integration is that CI will automatically run R CMD check (along with your tests, etc.) every time you push a commit to GitHub. You don’t have to remember to do this; CI automatically checks the code after every commit. Travis-CI is a continuous integration service that builds and tests projects that are hosted on GitHub; if your R package is open source (i.e., not private), then using Travis-CI is free.”

To set up CI, use the following usethis functions:

use_travis()
use_appveyor()
use_coverage(type = c("codecov"))

Again, this is outside the scope of this tutorial, but we leave it here for you to explore.

Add unit testing

You will most likely also want to include unit testing, this can be achieved using the testthat package. To do this, use the use_testthat() function.

use_testthat()
✔ Adding 'testthat' to Suggests field in DESCRIPTION
✔ Adding '3' to Config/testthat/edition
✔ Creating 'tests/testthat/'
✔ Writing 'tests/testthat.R'
• Call `use_test()` to initialize a basic test file and open it for editing.
use_test("my-test")
✔ Writing 'tests/testthat/test-my-test.R'
• Edit 'tests/testthat/test-my-test.R'

Add spell check

Next we will add spell checking to our workflow, this is done with

# install.packages("spelling")
use_spell_check()
✔ Adding 'spelling' to Suggests field in DESCRIPTION
✔ Adding 'en-US' to Language
No changes required to /private/var/folders/7r/39cms9lx3rncwj6f5myx2fz40000gn/T/RtmpKhDIkN/mypkg/inst/WORDLIST
Updated /private/var/folders/7r/39cms9lx3rncwj6f5myx2fz40000gn/T/RtmpKhDIkN/mypkg/tests/spelling.R
• Run `devtools::check()` to trigger spell check

Make sure that the spelling package is installed before running.

Create data folder and objects

If you are going to include data in your package, you would want to include a data-raw folder where the data is created/formatted.

use_data_raw()
✔ Creating 'data-raw/'
✔ Adding '^data-raw$' to '.Rbuildignore'
✔ Writing 'data-raw/DATASET.R'
• Finish the data preparation script in 'data-raw/DATASET.R'
• Use `usethis::use_data()` to add prepared data to package
x <- 1
y <- 2
use_data(x, y)
✔ Adding 'R' to Depends field in DESCRIPTION
✔ Creating 'data/'
✔ Setting LazyData to 'true' in 'DESCRIPTION'
✔ Saving 'x', 'y' to 'data/x.rda', 'data/y.rda'
• Document your data (see 'https://r-pkgs.org/data.html')

Add NEWS file

Lastly if you plan on doing a little larger project a NEWS file is very handy to keep track on what is happening in your package.

use_news_md()

Add packages to DESCRIPTION file

You can also add packages to the DESCRIPTION file

For example, here we are adding the MASS package to the Suggests description field.

use_package("MASS", "Suggests")
✔ Adding 'MASS' to Suggests field in DESCRIPTION
• Use `requireNamespace("MASS", quietly = TRUE)` to test if package is installed
• Then directly refer to functions with `MASS::fun()`
use_package("dplyr")
✔ Adding 'dplyr' to Imports field in DESCRIPTION
• Refer to functions with `dplyr::fun()`

Set up documentation files

We can set up the documention files using Roxygen

use_roxygen_md()

Multiple time modifications

Now that we have setup all the basics, the general development can begin.

You typical workflow will be repeating the following steps in the order that suits your flow

  • Write some code
  • Restart R Session Cmd+Shift+F10 (Ctrl+Shift+F10 for Windows)
  • Build and Reload Cmd+Shift+B (Ctrl+Shift+B for Windows)
  • Test Package Cmd+Shift+T (Ctrl+Shift+T for Windows)
  • Check Package Cmd+Shift+E (Ctrl+Shift+E for Windows)
  • Document Package Cmd+Shift+D (Ctrl+Shift+D for Windows)

Create .R files and unit tests for functions

use_r("function_name")
• Edit 'R/function_name.R'

This function is very important and you will using it a lot, not only will it create the files you save your functions in, but it will also open the files if they are already created, this makes navigating your R files much easier. Once you have created your function it is time to add some tests! This is done using the use_test() function, and it works much the same way as the use_r().

use_test("function_name")
✔ Writing 'tests/testthat/test-function_name.R'
• Edit 'tests/testthat/test-function_name.R'

Create a vignette

An vignette provides a nice piece of documentation once you have added a bunch of capabilities to your package.

use_vignette("my_cool_vignette")
✔ Adding 'knitr' to Suggests field in DESCRIPTION
✔ Adding 'rmarkdown' to Suggests field in DESCRIPTION
✔ Adding 'knitr' to VignetteBuilder
✔ Adding 'inst/doc' to '.gitignore'
✔ Creating 'vignettes/'
✔ Adding '*.html', '*.R' to 'vignettes/.gitignore'
✔ Writing 'vignettes/my_cool_vignette.Rmd'
• Edit 'vignettes/my_cool_vignette.Rmd'

Summary

You should be off and running now!