knitr::opts_chunk$set(echo = TRUE)
My 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:
devtools::install() library(mycensus)
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.
View the vignette for mycensus using use_vignette()
, but a better way to document packages will be through the pkgdown
package.
library(mycensus) # check out the documentation! ?mycensus ?get_decennial_recs
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.