knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE,
                      error = FALSE, results = "asis")

Writing an R package:

Tools--R packages to create R packages

  1. devtools is a collection of R package developmental tools
    • For example create("project") creates a project folder for your R package
  2. usethis creates things for package management
    • For example use_r("file_name") creates an .R file
  3. roxygen generates documentations

More on how to use these packages below... ...

HOW to Create an R Package:

  1. Navigate to the desired project location with setwd() in RStudio
  2. Use devtools::create("<project_name>") to create a new R project. It will create the following files inside the project folder:
    • an R folder
    • DESCRIPTION
    • NAMESPACE
    • .Rproj
    • If existing project doesn't have an .Rproj file, create one with devtools::use_rstudio("<path/to/package>"). .Rproj file contains project option information
    • .gitignore
    • .Rbuildignore
  3. Work on the DESCRIPTION file, reference for details here:
    • Modify Title and Description accordingly (Note: values span multiple lines in the DESCRIPTION file needs four spaces indent)
    • Modify Authors@R with person("first_name", "last_name", email = ..., role = c("aut", "cre"))
    • Use devtools::use_package("package_name") to add package dependency to Import:
    • Use devtools::use_package("package_name", "Suggests") to add package to Suggests:
    • If any of your functions provides the option to use the suggested package, check if the package is installed with requireNamespace("package_name", quietly=TRUE)
    • Use devtools::use_build_ignore("note") to modify the .Rbuildignore file
  4. Add functions to .R files in the R folder:
    • use_this::use_r("file_name") to creat a blank .R file in the R folder
    • Tips and tricks for functions:
    • Variable names should be nouns and function names should be verbs
    • Use two spaces when indent your code
    • Comments should explain the why, not the what
    • Use #------ to break up your code into easily readable chunks
    • Add function documentation:
    • Title in the format of #' @title <fxn title>
    • Description in the format of #' @description <fxn description>
    • Parameter(s) in the format of #' @param <name> <description>
    • Output in the format of #' @return <fxn outupt>
    • Example of how function is used in the format of #' @example(s) <example> (Note: example will need to pass check if it's added to documentation)
    • Don't forget to #' @export Example
    • devtools::document() creates the nicely formatted function documentations, which are in the Rd files, and they could be converted to HTML or PDF
    • use template .R file or template documentation (#'@template file_name), or documentation referencing (#'@inheritParams function_name) for consistent function documentation
  5. To add the magrittr pipe, use usethis::use_pipe()
  6. Add files/directories to .Rbuildignore if they should not be distributed
    • usethis::use_build_ignore("<file/directory_name>")
  7. Build package with devtools::build()
  8. Check package for errors, warnings, and notes with devtools::check()
  9. Use GitHub Actions to check codes add to the repo:
    • usethis::use_github_action_check_standard() for standard check
    • usethis::use_github_action_check_release() for quick check
    • Either function creates a .github folder, a workflows folder with a R-CMD-check.yaml file inside, and a R-CMD-check badge will be added to the README.md

How to Consistently Document R Functions

Create a Template .R File

Reference: stackoverflow post

  1. First create a template folder in the .config folder
    • cd ~/.config/rstudio
    • mkdir template
  2. Then create a default.R file
    • cd template
    • touch default.R
    • open default.R and add to the default.R file

Create a Template Doc File

Reference: technical guidelines from Mirai Solutions

  1. First create a man-roxygen folder in the project folder
  2. Add the folder to the .Rbuildignore
    • usethis::use_build_ignore("man-roxygen")
  3. Create template documentation .R file
    • For example, "#'@param var_x blah blah blah" to var_x.R

Understand the WHYs

Reference: first edition of R Packages, second edition is work in progress.

  1. What is the difference between devtools and usethis? Hmmm
  2. Five states of a package:
    • source: local development version of a package
    • bundled: package that's compressed to a single file, it's created by calling devtools::build(). Files added to ".Rbuildignore" are not included in the bundle. Package bundle is generated for code distribution!?
    • binary: similar to package bundle that it's compressed to a single file, but its internal structure is rearranged from a source package. Binary package is generated for distribution that install.packages() download and install binary packages built by CRAN.
    • installed: is a binary package decompressed into a package library
    • in memory: load installed package to memory
  3. What is a library? A directory containing installed packages. Library varies based on the version of R. When upgrade R, all packages need to be re-install not because they disappear, but only that R cannot find them.
  4. What is the difference between devtools::load_all() and "Build & Reload"?
    • devtools::load_all() sources all files in R/
  5. What is the difference between library() and require()? When a package is not found, library() throws an error but require() prints a message and returns FALSE.
  6. When a package is built, code in R/ is executed and the results are saved. They are made available to use when package is loaded with library() or require().
  7. DESCRIPTION lists the packages your package needs. Specify required packages in DESCRIPTION$Imports and they will be installed when your package is installed. List suggested packages under DESCRIPTION$Suggests, those are the packages can be used but not required (Not sure if I understand the difference since I would have suggested_package::fxn even for functions from the suggested packages in my codes, right?! Okay, I think it means if you have an alternative execution to suggested_package::fxn, you can let your package users know that they can use the suggested_package::fxn with your fxns). For examples:
# Here you are telling your package users that they need to install the suggested_pkg.
# Why not put the package under Imports?? If the suggested package is only required 
# by one less-frequently-used function among many of your other functions, maybe it's 
# a good idea to let the users install the suggested package when they need it.
# When developing package locally, you don't really need to use Suggests.
fxn <- function(x, y) {
  if (!requireNamespace("suggested_pkg", quietly = TRUE)) {
    stop("Suggested_pkg needed for this function. Please install it.", call. = FALSE)
  }
}

# Here you have an alternative execution, but user could also choose to use the 
# suggested package
fxn <- function(x, y) {
  if (!requireNamespace("suggested_pkg", quietly = TRUE)) {
    suggested_pkg::fxn()
  } else {
    fxn()
  }
}
  1. Version of the required packages under Imports: can be specified like this:
Imports: 
  pakcage_x (>= version_of_the_pacakge_you_are_using_for_development)

It's important to specify the version of required packages when you release your package since users might not have the required version installed. 9. 10. R environment is changed sometimes with function calls, for examples, library(), options(), and setwd()



sarazong/SZRtools documentation built on Feb. 8, 2024, 6:49 a.m.