A package is a collection of functionality designed to achieve one or more purposes. Commonly it is a bundle of functions that help tackle a certain type of analysis.
Packages are great ways to modularise your code and create standardised ways of doing specific tasks in your organisation, like charts (optiRum::theme_optimum()
).
There is an R foundation guide to writing packages. I don't recommend you start with that! It is however what any package that you submit to the central repository of R packages (CRAN) will be held against - so if you'd like to get a package on CRAN you will need to read this.
The better, more accessible book R packages is by Hadley Wickham and will cover things in a lot of depth but is more accesable and has exercises.
For quick learning abotu devtools you can check out the cheatsheet
The easiest way to build a good quality package is to use the package devtools. This is a package designed specifically to make life easier for package developers.
Here is my typical workflow:
library(devtools)
pkg<-"newPackage"
create(pkg)
# Open the project!
library(devtools)
# Add unit test framework
add_test_infrastructure()
# Add CI framework
add_travis()
# Add folder for macro-level help files
use_vignette()
# Add file for providing info about your package
use_package_doc()
# Add a file for storing comments about the release if submitting to CRAN
use_cran_comments()
# Create various useful files
file.create("README.md")
file.create("NEWS")
# Set git up
library(git2r)
init(".")
Once I have this skeleton I fill in the various bits of info about my package in DESCRIPTION, README, R/package.R, and so forth.
After I've done some basic hygiene, I can start building my R functions and associated tests.
...
) argument to pass values through to optional components in functions#' A function quick description
#'
#' A more detailed description that can span multiple lines
#' for readability. Covers concepts, typical usages etc.
#'
#' @param param1 Info about param1 e.g. data type, guidance
#' @param param2 Info about param1 e.g. data type, guidance
#' @param ... Additional values to pass to x, y, z
#'
#' @return returnDT Info about what is returned by the function
#'
#' @keywords words allowing search
#' @family ifPartOfABundle
#'
#' @examples
#' # Sample code that illustrates usage
#'
#' @export
myFuncName<- function(param1, param2="Blah", ...){
stopifnot(param1>0, is.character(param2))
# Function code routinely commented with WHY or
# explanations of complex HOW (but consider
# breaking these up / simplifying)
}
Let's make sure your code is all working (assumes you've got unit tests)
library(devtools)
# Build help files
document()
# Run unit tests
test()
# Check against CRAN standards
check()
Each of these steps could identify things to fix. It's great to get rid of as many ERRORs, WARNINGs, and NOTEs as possible.
There are a number of locations but I'll cover two:
My personal recommendations are to use GitHub as your active development environment, so that people can download the latest version, and periodically attempt to release to CRAN. This helps push up your package quality and makes your code more widely available.