Creating R packages

Andrea Sánchez-Tapia , Sara Mortara
2022-08-09

We are going to go through the process of creating an R package. We will use the helper functions inside package usethis, it’s the easiest workflow today.

Packages needed

install.packages("devtools")
install.packages("usethis")
install.packages("available")

Check if you have the developer tools installed:

devtools::has_devel()

To create your package, open a new session of RStudio, not inside an Rproject.

Select a location outside your repository for this course.

usethis::create_package("../foo")

RStudio will ask you to confirm you want the create the project with the package. After you accept, it will start a new session in project “foo”

File structure

Check the folder structure that was created by usethis

It has files NAMESPACE, DESCRIPTION, an empty R subfolder where the functions will be created.

It also has a .gitignore file (it’s ready to be a git repository)

and a .Rbuildignore file where you should list files that won’t be used by the package. For example, if you have a script inside the folder for creating the folder, it should be listed there.

DESCRIPTION

NAMESPACE

And close it :) Do not edit by hand. We’ll see what roxygen2 does soon.

Let’s add a function

We won’t be creating a complicated function. We can use our Shannon diversity function from previous sessions.

Copy the code for the function in a new file inside /R: R/my_shannon.R

You can create this file by hand or use: usethis::use_r("my_shannon")

It will open an empty file. Copy the Shannon diversity function from this chunk:

my_shannon <- function(x) {
  x <- x[x > 0]
  sum_all <- sum(x)
  pi <- x/sum_all
  -sum(pi*log(pi))
}

Save and close

Checking the package

We will be checking if the package caBn load without installing it:

devtools::load_all()

You can already execute the function my_shannon() in the console 🎉

my_shannon(1)
my_shannon(c(1, 2, 3))

Now we need to create the documentation and some tests.

Documenting functions

Let’s add an roxygen2 header to the function.

It will add some special comments with a single quote #'

#' @param x A vector with values of abundance in the community

The field @return allows you to describe what type of return you will get. Edit it so it looks like this:

#' @return A numeric vector of length 1 with the value of the Shannon diversity 

The field @export tells R to export the function, to make it available in the workspace.

The field @examples allows you to add some example of how the function would be used:

#' @examples 
#' com <- c(1, 2, 3)
#' my_shannon(com)

Examples are optional and not recommended if they take too long to run. They will be executed later by the tests of the packages, so they have to run.

After you finished editing the roxygen2 header, we can create the documentation with:

devtools::document()
Updating foo documentation
ℹ Loading foo
Writing NAMESPACE
Writing my_shannon.Rd

Check inside the /man subfolder. We have a new file my_shannon.Rd with the correct documentation format.

To see how it parses, you can ask for the help of the function:

?my_shannon

The help menu should open:

Run CRAN checks

devtools has a function that emulates the checks run by CRAN when you submit a package.

devtools::check()

It will run the examples, the tests, and the vignettes. It will also check for the size of the package, the time that examples take to run, and more.

In more complex examples, devtools::check() will return errors, warnings and notes. All of them need to be adressed, especially the errors and warnings. Some of these will not allow you to load or install the package.

Testing the functions

It’s best to add tests for every function in the package. The percentage of code that is covered by tests is commonly called the coverage.

Tests are saved in the /tests subfolder.

Executing:

usethis::use_test("my_shannon")

Will add a tests/test-my_shannon.R file

Testing with testthat package has many complex options. We can check a particular value

expect_equal(my_shannon(1), 0)

You can add this line between the brackets of the test file and save.

Click Run Test in the top right corner of the editor pane

We can also expect for objects types

expect_type(my_shannon(c(1, 2, 3)), "double")

and save the snapshot for a know error, to check if it changes

expect_snapshot_error(my_shannon("a"))

Add these options between the brackets

You can check the package again, it will run the tests now.

devtools::check()

Add a README

usethis::use_readme_rmd()

The .Rmd file allows you to add figures and code easily. To generate a README.md, knit the Rmd using the Knit button or ctrl+shift+K.

The first time it will probably return an error because the Rmd calls for library(foo). We have to install the package.

Install your own package locally

devtools::install()

Now you can call

library(foo)

and knit the README.Rmd file.

Put the package online so anyone can install it!

This package should be a git repository.

The command

usethis::use_git()

Will run the equivalent to git init and add some files to .gitignore.

Do the commit of the whole package, adding your informative commit message.

Uploading to GitHub

Now we need to create a remote repository in GitHub and push our package to it.
Although there are ways to do this in usethis, depending on each one’s configuration we’d rather do it by hand.

Execute in the terminal:

git remote add origin git@github.com:YOURHANDLE/foo.git

git push -u origin main

Now the whole package should be in GitHub.

To install remotely!

remotes::install_github("YOURHANDLE/foo")

And you created your first R package :)

Don’t forget to update the README.Rmd file with the installation instructions!

Update DESCRIPTION with the following fields:

URL: https://github.com/YOURHANDLE/foo
BugReports: https://github.com/YOURHANDLE/foo/issues

Save and commit.

Notes:

devtools::document()
devtools::check()

Remote checks using GitHub actions

usethis::use_github_action_check_standard()

Knit the README, and add and commit everything.

Create a website for your package

library(pkgdown)
usethis::use_github_action("pkgdown")

Commit the files created and wait for GitHub to build the site.

The website was built in a second branch, gh-pages. To enable it, go to the repository settings, look for Pages and enable the pages from the gh-pages branch and the docs/ folder. Click Save.

The site is ready at https://YOURHANDLE.github.io/foo/

Add the URL of your package site in the About section of the repository, in the URL: field of the _pkgdown.yml file and in the DESCRIPTION, in the URL field, separated from the repository URL by a comma.