create-r-packages.RmdMy toy example and what I will reference throughout this document is here: https://github.com/cyyllam/mycensus
This document is a collection of notes and instructions gathered from the following sources:
Creating a package will make use of the following packages:
devtools: contains tools to document, check, test, and
install your package.roxygen2: documentation headers above your functions
that will help create R documentation when the user asks for help.usethis: automates workflow e.g. providing functions to
insert information into a file or telling testthat to set up a testing
framework for unit testing.testthat: contains tools e.g. expect_*()
to conduct unit tests.Depending on what you’re doing, Rtools may be required.
Create package using RStudio’s template. This creates a directory with an .Rproj file so your working directory is already set-up.
New R Project icon >
New Directory > New Package
The name of your package should only contain letters, numbers, or dots.
The DESCRIPTION file contains author and maintainer details, package dependencies, and license details.
To add a package dependency, you can use
usethis::use_package(). It will automatically insert
whatever package you provide.
cre = maintainer (who should get an email if something
goes wrong)
The NAMESPACE file that exists when you create your package directory is a minimalist file. Delete it!
This file will be re-created and updated when you run the
devtools::document() after completing documentation on your
functions.
The NAMESPACE file is something that you do not edit by hand.
Add functions in one or across multiple R files in the R
directory.
Place cursor in the body of your function. Use Ctrl +
Alt + Shift + R to add Roxygen2
commenting structure and edit accordingly.
Examples:
You can run devtools::document() to convert scripts with
roxygen headers to .Rd files. These are the R Documentation Help files
when use ? or help() to check function
details.
@export is used for functions you want to be made
available to the user. It will export the function to the NAMESPACE and
when the user starts typing mycensus:: only exported
functions will appear in the intellesense.
To document the package itself, you can store the following at the top of a script with roxygen headers. It can also be in a separate file.
#' mycensus: A package for easy compilation of census estimates for the Puget Sound Region.
#'
#' This package provides functions to easily collect census estimates across geographies within the
#' Central Puget Sound region.
#'
#' @author Christy Lam \email{clam@psrc.org}
#' @docType package
#' @name mycensus
"_PACKAGE"
utils::globalVariables("GEOID")Using variable names in dplyr functions may trigger warnings or notes
on undefined variables. Use the globalVariables at the top
of your script(s) to pass the checking stage.
When referencing column names within dplyr functions, use the
.data$ prefix e.g.
df %>%
dplyr::filter(.data$column_1 == 'x')Run the following:
devtools::document()devtools::check() to check package for errors,
warnings, and notes. Make sure to resolve all errors at the very least
before moving on.The check will run the examples listed in your header
@examples. Make sure your examples are reproducible!
Objects should be created or defined in some way.
An error that I got repeatedly was something along the lines of
‘<function> undefined’ or
‘<function> can’t be found’. Even though I added
e.g. @import dplyr in the roxygen headers. For every
function used, I identified the package followed by double colons
e.g. dplyr::filter().
See comments from Hadley Wickham in this SO: https://stackoverflow.com/questions/35750967/r-roxygen2-imported-packages-do-not-appear-in-namespace
After error checking and completing the DESCRIPTION file, add/commit/push to Github.
Install your package on your computer:
To distribute your package via Github have others run this command:
devtools::install_github("cyyllam/mycensus")Another way of distributing your package is to create a source file
(a .tar.gz file). Use devtools::build() and it
will generate a file outside of your package directory (I’m not sure
where to store the file though…).
To install a branch version of your package use the following command referencing your package repo and the branch name.
devtools::install_git('https://github.com/cyyllam/mycensus.git', ref = 'my-branch-name')After installing, check the package description to verify that the
ref is using the branch version and not main.
packageDescription('mycensus')Set-up test framework using usethis::use_testthat().
Save your tests as .R files in the tests/testthat/
directory with the prefix test-.
Use various expect_*() functions to conduct tests.
To group tests (for organization), use the function
testthat::test_that() like so:
testthat::test_that('get_deccenial_recs returns expected results', {
df <- mycensus::get_decennial_recs(geography = 'county',
table_codes = 'PCT013',
year = 2010)
# default counties are formatted with 'County, Washington'
testthat::expect_identical(unique(df$NAME), c('King County, Washington', 'Kitsap County, Washington', 'Pierce County, Washington', 'Snohomish County, Washington'))
# default columns from tidycensus are the follow six variables
testthat::expect_identical(colnames(df), c('GEOID', 'NAME', 'variable', 'value', 'label', 'concept'))
})To run all tests: devtools:test()
Consider using Travis CI (continuous integration) or
usethis::use_github_actions() (which I haven’t done yet).
Every time code is committed/pushed to Github, the R CMD Check and unit
tests will automatically run.
For more reading: https://juliasilge.com/blog/beginners-guide-to-travis/
(this was written back in 2016) and use_travis() is now
soft-deprecated. Documentation recommends
usethis::use_github_actions() for CI.