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:
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
- Create some new functions for your tempConvert package to convert from Celsius to Fahrenheit or from Kelvin to Celsius or Fahrenheit.
- 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.