Making Packages in R

Last updated on 2024-12-03 | Edit this page

Estimated time: 30 minutes

Overview

Questions

  • How do I collect my code together so I can reuse it and share it?
  • How do I make my own packages?

Objectives

  • Describe the required structure of R packages.
  • Create the required structure of a simple R package.
  • Write documentation comments that can be automatically compiled to R’s native help and documentation format.

Why should you make your own R packages?

Reproducible research!

An R package is the basic unit of reusable code. If you want to reuse code later or want others to be able to use your code, you should put it in a package.

An R package requires four components, visualized in the folder tree below:

package_name/
├── DESCRIPTION              # metadata about the package
├── man/                     # function documentation (can be generated automatically)
├── NAMESPACE                # list of user-level functions in the package (can be generated automatically)
├── R/                       # R source code
└── <other_components>

There are other optional components. rOpenSci community has written a science-focused guidebook for package development, while the “R packages” book contains all the fundamental information.

DESCRIPTION file

Package: package_name
Title: Brief package description
Description: Longer package description
Version: Version number(major.minor.patch)
Author: Name and email of package creator
Maintainer: Name and email of package maintainer (who to contact with issues)
License: Abbreviation for an open source license

The package name can only contain letters and numbers and has to start with a letter.

.R files

Functions don’t all have to be in one file or each in separate files. How you organize them is up to you. Suggestion: organize in a logical manner so that you know which file holds which functions.

Making your first R package

Let’s turn our temperature conversion functions into an R package.

R

fahrenheit_to_celsius <- function(temp_F) {
  # Converts Fahrenheit to Celsius
  temp_C <- (temp_F - 32) * 5 / 9
  return(temp_C)
}

R

celsius_to_kelvin <- function(temp_C) {
  # Converts Celsius to Kelvin
  temp_K <- temp_C + 273.15
  return(temp_K)
}

R

fahrenheit_to_kelvin <- function(temp_F) {
  # Converts Fahrenheit to Kelvin using fahrenheit_to_celsius() and celsius_to_kelvin()
  temp_C <- fahrenheit_to_celsius(temp_F)
  temp_K <- celsius_to_kelvin(temp_C)
  return(temp_K)
}

We will use the devtools and roxygen2 packages, which make creating packages in R relatively simple. Both can be installed from CRAN like this:

R

install.packages(c("devtools", "roxygen2"))  # installations can be `c`ombined
library("devtools")
library("roxygen2")

Set your working directory, and then use the create function to start making your package. Keep the name simple and unique.

  • package_to_convert_temperatures_between_kelvin_fahrenheit_and_celsius (BAD)
  • tempConvert (GOOD)

R

setwd(parentDirectory)
create_package("tempConvert")

Add our functions to the R directory. Place each function into a separate R script and add documentation like this:

R

#' Converts Fahrenheit to Celsius
#'
#' This function converts input temperatures in Fahrenheit to Celsius.
#' @param temp_F The temperature in Fahrenheit.
#' @return The temperature in Celsius.
#' @export
#' @examples
#' fahrenheit_to_celsius(32)

fahrenheit_to_celsius <- function(temp_F) {
  temp_C <- (temp_F - 32) * 5 / 9
  return(temp_C)
}

The roxygen2 package reads lines that begin with #' as comments to create the documentation for your package. Descriptive tags are preceded with the @ symbol. For example, @param has information about the input parameters for the function. Now, we will use roxygen2 to convert our documentation to the standard R format.

R

setwd("./tempConvert")
document()

Take a look at the package directory now. The /man directory has a .Rd file for each .R file with properly formatted documentation.

Overall, your package directory should look something like this:

tempConvert directory containing 4 items: Namespace file, Description file, man directory with documentation in .Rd files, R directory with functions in .R files

In the diagram above, your package is a folder (the same as it would exist on your computer!). This folder contains several files and sub-folders. For example, the folder ‘R’ contains all of the R scripts you just wrote above. Now, let’s load the package and take a look at the documentation.

R

setwd("..")
install("tempConvert")

?fahrenheit_to_kelvin

Notice there is now a tempConvert environment that is the parent environment to the global environment.

R

search()

Now that our package is loaded, let’s try out some of the functions.

R

fahrenheit_to_celsius(32)

OUTPUT

[1] 0

R

celsius_to_kelvin(-273.15)

OUTPUT

[1] 0

R

fahrenheit_to_kelvin(-459.67)

OUTPUT

[1] 0

Creating a Package for Distribution

  1. Create some new functions for your tempConvert package to convert from Celsius to Fahrenheit or from Kelvin to Celsius or Fahrenheit.
  2. Create a package for our analyze function so that it will be easy to load when more data arrives.

R

#' Converts Kelvin to Celsius
#'
#' This function converts input temperatures in Kelvin to Celsius.
#' @param temp_K The temperature in Kelvin.
#' @return The temperature in Celsius.
#' @export
#' @examples
#' kelvin_to_celsius(273.15)

kelvin_to_celsius <- function(temp_K) {
  temp_C <- temp_K - 273.15
  temp_C
}

R

#' Converts Celsius to Fahrenheit
#'
#' This function converts input temperatures in Celsius to Fahrenheit.
#' @param temp_C The temperature in Celsius.
#' @return The temperature in Fahrenheit.
#' @export
#' @examples
#' celsius_to_fahrenheit(0)

celsius_to_fahrenheit <- function(temp_C) {
  temp_F <- (temp_C * 9/5) + 32
  temp_F
}

R

#' Converts Kelvin to Fahrenheit
#'
#' This function converts input temperatures in Kelvin to Fahrenheit.
#' @param temp_K The temperature in Kelvin.
#' @return The temperature in Fahrenheit.
#' @export
#' @examples
#' kelvin_to_fahrenheit(273.15)

kelvin_to_fahrenheit <- function(temp_K) {
  temp_C <- kelvin_to_celsius(temp_K)
  temp_F <- celsius_to_fahrenheit(temp_C)
  temp_F
}

Key Points

  • A package is the basic unit of reusability in R.
  • Every package must have a DESCRIPTION file and an R directory containing code. These are created by us.
  • A NAMESPACE file is needed as well, and a man directory containing documentation, but both can be autogenerated.