4 R Packages
This chapter walks you through the process of creating an R package, from setting up your development environment to sharing your package with the world. Each step is explained in detail to help you understand the package development process.
4.1 Set up the development environment
To begin creating your R package, you need to set up your development environment:
- Install the operating system tools required for package development:
- If on macOS, install Xcode Command Line Tools by running
xcode-select --install
in the terminal. - If on Windows, install Rtools from https://cran.r-project.org/bin/windows/Rtools/
- If on Linux, install the R development package using your package manager (e.g.,
sudo apt-get install r-base-dev
)
- If on macOS, install Xcode Command Line Tools by running
- Install necessary R development packages by running the following commands in the R console:
install.packages(c("devtools", "roxygen2", "testthat", "knitr"))
These packages will help you with package development, documentation, testing, and vignette creation.
4.2 Create the package structure
To create your package structure:
- In RStudio, go to File > New Project > New Directory > R Package.
- Choose a name for your package.
- Use only letters, numbers, and periods in the name.
- Avoid using hyphens or underscores.
- Select a directory where you want to create your package.
- Click “Create Project”.
This will create a new directory with the basic structure of an R package, including:
.
├── DESCRIPTION # Metadata about your package
├── NAMESPACE # Exporting and importing code
├── R # Directory for your R code
│ └── hello.R
├── MyPackage.Rproj # RStudio project file
└── man # Directory for documentation
└── hello.Rd
4.3 Edit the DESCRIPTION
file
The DESCRIPTION
file contains metadata about your package. Edit it to include:
- Package: Your package name
- Title: A short, one-line description of your package
- Version: Start with “0.1.0” for a new package
- Author: Your name and email
- Maintainer: Usually the same as the Author
- Description: A more detailed description of what your package does
- License: Choose an appropriate license (e.g., GPL-3, MIT, CC0)
- Imports: List the packages your package depends on
- Suggests: List packages used for examples or tests
Example:
Package: mypackage
Title: What The Package Does (One Line, Title Case)
Version: 0.1.0
Author: Your Name <your.email@example.com>
Maintainer: Your Name <your.email@example.com>
Description: More about what it does (maybe more than one line).
License: AGPL-3
Imports:
dplyr,
ggplot2
Suggests:
testthat,
knitr
4.4 Write R functions
To add functions to your package:
- Create new R script files in the
R/
directory of your package. - Write your functions in these files.
- Use meaningful names for your files and functions.
- Keep related functions in the same file.
Example function in R/hello.R
:
#' Say hello to a person
#'
#' This function takes a name as input and returns a greeting.
#'
#' @param name A character string representing a person's name
#' @return A character string with a greeting
#' @export
<- function(name) {
hello paste0("Hello, ", name, "!")
}
The #'
comments are roxygen2 documentation, which we’ll cover in the next step.
4.5 Document your functions
To document your functions:
- Use roxygen2 comments (starting with
#'
) above each function. - Include a brief description, parameter details, return value, and examples.
- Use tags like @param, @return, @examples, and @export.
- Run
devtools::document()
to generate documentation files.
Let’s create a new function called square()
and document it with roxygen2.
Example function and inline documentation in R/square.R
:
#' Calculate the square of a number
#'
#' This function takes a numeric input and returns its square.
#'
#' @param x A numeric value
#' @return The square of the input value
#' @examples
#' square(4)
#' square(-2)
#' @export
<- function(x) {
square stopifnot(is.numeric(x))
^2
x }
After writing your documentation, run devtools::document()
to generate the man/
files and update the NAMESPACE
.
The package structure should now look like this:
.
├── DESCRIPTION # Metadata about your package
├── NAMESPACE # Exporting and importing code
├── R # Directory for your R code
│ ├── hello.R
│ └── square.R
├── MyPackage.Rproj # RStudio project file
└── man # Directory for documentation
├── hello.Rd
└── square.Rd
4.6 Add data (optional)
The packages have the ability to automatically load data on demand when the package is loaded.
To include datasets in your package:
- Create a
data/
directory in your package if it doesn’t exist. - Save your dataset using
save()
. For example:save(my_data, file = "data/my_data.rda")
- Document your dataset using roxygen2 comments in an R file (e.g.,
R/data.R
).
Example dataset documentation in R/data.R
:
#' Example dataset of plant growth
#'
#' A dataset containing plant heights and treatments.
#'
#' @format A data frame with 30 rows and 2 variables:
#' \describe{
#' \item{height}{Plant height, in cm}
#' \item{treatment}{Treatment group (A, B, or C)}
#' }
#' @source {Made up data for illustration}
"plant_growth"
The package structure should now look like this:
.
├── DESCRIPTION # Metadata about your package
├── NAMESPACE # Exporting and importing code
├── R # Directory for your R code
│ ├── hello.R
│ └── square.R
├── data # Directory for datasets
│ └── plant_growth.rda
├── MyPackage.Rproj # RStudio project file
└── man # Directory for documentation
├── hello.Rd
├── plant_growth.Rd
└── square.Rd
4.7 Write tests
Regular testing helps ensure your package functions work as expected and helps catch bugs early. We recommend using the testthat package for testing instead of just running checks of R code.
To write tests for your package:
- Create a
tests/testthat
directory if it doesn’t exist. - Create a
testthat.R
file in thetests/
directory to load the test files.- This file should contain
library(testthat)
,library(MyPackage)
, andtest_check("MyPackage")
.
- This file should contain
- Create test files with names starting with
"test-"
(e.g.,test-square.R
). - Use testthat functions like
expect_equal()
,expect_error()
, etc. - Run tests using
devtools::test()
.
Test infrastructure is set up using
::use_testthat() usethis
You can quickly create a test for an open R script using
::use_test() usethis
Example test file (tests/testthat/test-square.R
):
test_that("square(): works correctly", {
expect_equal(square(2), 4)
expect_equal(square(-3), 9)
expect_equal(square(0), 0)
})
test_that("square(): handles non-numeric input", {
expect_error(square("a"))
expect_error(square(TRUE))
})
4.8 Build and check the package
To build and check your package:
- Run
devtools::build()
to create a package bundle. - Run
devtools::check()
to perform a comprehensive check of your package. - Address any warnings or errors reported by the check.
Common issues to watch for:
- Undocumented functions or parameters
- Missing or incorrect NAMESPACE entries
- Code that doesn’t pass R CMD check
- Vignette building problems
Aim to have your package pass R CMD check with 0 errors, 0 warnings, and 0 notes for the best chance of CRAN acceptance.
4.9 Create a README.md
and vignettes
Creating documentation:
- Write a README.md file in the package root directory:
- Include a brief description of your package
- Provide installation instructions
- Show a simple example of package usage
- Add any badges (e.g., CRAN status, build status)
- Create vignettes to provide in-depth tutorials:
- Use
usethis::use_vignette("my-vignette")
to set up a vignette - Write your vignette using R Markdown or Quarto.
- Include examples, explanations, and use cases
- Use
Example README.md structure:
# MyPackage
<!-- badges: start -->
<!-- badges: end -->
## Overview
Brief description of what your package does.
## Installation
You can install the package from GitHub:
```r
# install.packages("remotes")
::install_github("username/MyPackage")
remotes```
## Usage
Basic example of how to use your package:
```r
library(MyPackage)
<- square(5)
result
result```
## More Information
For more detailed information, please refer to the vignettes:
```r
browseVignettes("MyPackage")
```
4.11 Conclusion
Making an R package is a rewarding process that allows you to share your code and contribute to the R ecosystem. Through these steps, you can create a well-structured, documented, and tested R package ready for distribution.
Remember that package development is an iterative process, and you may find yourself revisiting these steps as you refine and expand your package.