::create_package('path_to_pkg/pkgname') usethis
R package workflow
A step-to-step guide to make CRAN-worthy R packages
This checklist is being updated over time. Mostly for my own use; but great if it helps you as well!
For a complete treatment, please refer to R Packages (2e) by Hadley Wickham and Jennifer Bryan.
- initialize project, edit
DESCRIPTION
, search and replace with your package name - create package planning documentation, put inside
dev/
- create a minimal function with documentation, test and vignette
- build package, check
- create data related files and documentation
- build pkgdown website
- build package, check
- push to github, deploy pkgdown website
- github action configure lifecycle and R CMD check
Start building your package
The usethis
package will help with the procedure when you do not have a package yet.
You can also create a template, and copy paste from it in the future.
Initialize the project
It opens a new R project (directory) named pkgname
, with the following items:
DESCRIPTION
NAMESPACE
- directory
R/
.Rbuildignore
and.gitignore
- and the project icon,
pkgname.Rproj
.
If you have an existing R project but wish to build a package there, copy everything but pkgname.Rproj
, and modify the files in your existing pkg directory. Pay extra attention to the hidden files like .Rbuildignore
.
::use_mit_license() # modify name to yours
usethis::use_readme_md() # if you do not have this already
usethis::use_news_md()
usethis::use_test()
usethis
# create a folder for future data documentation
<- 1
x ::use_data() usethis
In addition, URL and bug reports should be added in the DESCRIPTION
.
Planning
It is good practice to start with planning the package, rather than directly start coding.
Create a folder called dev
. To prevent it from being built, add the following line in .Rbuildignore
Write, test and document
Create exported functions in R/
, development code in script/
(or somewhere else, such as dev/
).
Data: raw and processed
Need to be clear in mind where the data files go. There are a few data related folders:
- raw data files, in the format of excel sheets or csv. Usually placed as
inst/data_name.csv
- R scripts to process the raw data so that we create data object inside the package, put inside
data-raw
- data objects that can be called as
pkg::data_name
, are placed indata
. These files are usually directly generated by executingwrite.rda()
. - data documentation, usually placed in
R/data_documentation.R
. These are Roxygen2 documents for the data.
Documentation
You need to configure the Build tools.
These three things should be done:
Function documentation
Create a function f1
, and put your cursor on it. Go to Code -> Insert Roxygen Skeleton to create the template.
Alternatively, use #'
to start.
#' A simple placehold function
#'
#' @param x a numeric value
#'
#' @return a value 3 greater than the input
#' @export
#'
#' @examples
#' f1(5)
<- function(x){
f1 +3
x }
Data documentation
It can be beneficial to create a separate file to document data only, say data_documentation.R
under the R/
directory.
#' Placeholder data x
#'
#' This dataset contains one value, x
#'
#' @format
#' \describe{
#' \item{x}{The placeholder data x}
#' }
#' @examples
#' print(x)
"x"
Vignette documentation
::use_vignette('your_vignette') usethis
Deploy to pkgdown
Check this reference here
Build package and check
It is possible that your checks don’t pass on the first try.
What to ignore when build?
^.*\.Rproj$
^\.Rproj\.user$
^dev$
^_pkgdown\.yml$
^license\.md$
Makefile
data-raw
cran-comments.md
^\.github$
Don’t forget to check these!
These aspects are quite important to check as well: documentation, code quality, exceptions among others.
Documentation
Sufficient, working examples
README.md
- Help pages
- Vignettes
Example code coverage, covr::package_coverage()
, use GHA workflow to check if code coverage is above a threshold.
Detect broken README
examples by generating README.md
on every commit.
In help pages, some examples have tags:
\dontrun{}
: not run byexample()
, not run byR CMD check
\donttest{}
: run byexample()
but not checked\dontshow{}
: run and checked
# code coverage
::package_coverage(type = c('examples', 'vignettes'), commentDonttest = F, commentDontrun = F)
covr
# readme examples
::render("README.rmd", output_format = rmarkdown::github_document())
rmarkdown
# help page examples
::run_examples(run_dontrun = T, run_donttest = T)
devtools
# check vignette examples
::build_site() pkgdown
Links and spelling errors
Detect link rot with urlchecker::url_check()
Spelling, check with spelling::spell_check_package()
or usethis::use_spell_check()
.
- specify prefered standard in
DESCRIPTION
- create a list of allowed misspelt words, put it under inst.
Handling exceptions
Error > warning > message
Code quality
Style guide, styler::style_pkg()
enforces tidyverse style guide.
Lint (code smells). Can be removed with styler
# code quality assessment
lint(text = 'x = 1') # with lint
lint(text = 'x <- 1') # no lint
::lint_package() lintr
CRAN Submission
Final checks
When you are almost ready to submit your package to CRAN, you need to do a few checks.
A good practice is to check while you build your package, so that you’ve already fixed most of the problems by the time you do the final check.
These are a few final checks to do.
# spell check
::spell_check()
devtools
# windows check
::check_win_devel()
devtools
# rhub cran check
::check_for_cran() rhub
Remember to check your email and fix potential problems! Some problems pop up in different places, so make sure you fix as many as possible.
Submit
There are a few ways to submit. I found this one to be the most convenient way:
::release() devtools
It asks a few questions to remind you whether all the checks havve passed, and whether you’ve updated the relevant information in DESCRIPTION
, NEWS
. In the end, it creates a tar ball and submits automatically to CRAN.
You need to check your email to confirm submission, just like when you do it manually via the webform.
Alternatively, you can either
- write
R CMD build PKGNAME
in the terminal; - in Rstudio, in
Build
tab select build binary.
Afterwards, submit manually via the webform.