R Packages Create
An R package is a structured collection of functions, data, and documentation bundled together for easy distribution and reuse. Creating your own package lets you share your tools with colleagues or the world, forces you to write clean documented code, and makes your workflow reproducible.
Package Structure
mypackage/ ├── DESCRIPTION ← package metadata (name, version, author) ├── NAMESPACE ← what functions to export (auto-generated) ├── R/ ← all your R function files │ ├── statistics.R │ └── plots.R ├── man/ ← documentation (.Rd files, auto-generated) ├── tests/ ← unit tests │ └── testthat/ ├── data/ ← included datasets (.rda files) └── vignettes/ ← long-form tutorials
Setting Up the Tools
install.packages(c("devtools", "usethis", "roxygen2", "testthat"))
library(devtools)
library(usethis)
Step 1: Create the Package Skeleton
# Creates the folder structure automatically
usethis::create_package("C:/R_Projects/mypackage")
# Or from RStudio: File → New Project → New Directory → R Package
Step 2: Write Your Functions (in R/ folder)
# File: R/statistics.R
#' Calculate the coefficient of variation
#'
#' @param x A numeric vector
#' @param digits Number of decimal places to round to
#' @return Coefficient of variation as a percentage
#' @examples
#' cv(c(10, 20, 30, 40, 50))
#' @export
cv <- function(x, digits = 2) {
if (!is.numeric(x)) stop("x must be numeric")
result <- (sd(x) / mean(x)) * 100
round(result, digits)
}
#' Normalize a numeric vector to 0-1 range
#'
#' @param x A numeric vector
#' @return Normalized vector with values between 0 and 1
#' @export
normalize <- function(x) {
(x - min(x)) / (max(x) - min(x))
}
The #' comments are roxygen2 documentation. They generate help pages automatically. The @export tag makes the function available when someone loads your package.
Step 3: Fill in DESCRIPTION
Package: mypackage
Title: Useful Statistical Utilities
Version: 0.1.0
Authors@R: person("Your", "Name", email="you@email.com", role=c("aut","cre"))
Description: Provides helper functions for common statistical tasks
including normalization and coefficient of variation.
License: MIT + file LICENSE
Encoding: UTF-8
Depends: R (>= 4.0.0)
Imports:
ggplot2,
dplyr
Suggests:
testthat (>= 3.0.0)
Step 4: Generate Documentation
devtools::document() # Reads roxygen2 comments → creates man/*.Rd files # Updates NAMESPACE automatically
Step 5: Write Tests
usethis::use_testthat()
usethis::use_test("statistics")
# File: tests/testthat/test-statistics.R
test_that("cv returns correct value", {
expect_equal(cv(c(10,20,30,40,50)), 52.7)
expect_error(cv("text"), "x must be numeric")
})
test_that("normalize outputs 0 to 1 range", {
result <- normalize(c(0, 5, 10))
expect_equal(result, c(0, 0.5, 1))
expect_true(all(result >= 0 & result <= 1))
})
Step 6: Run Checks and Build
devtools::load_all() # load package for testing in current session devtools::test() # run all tests devtools::check() # full CRAN-style check (errors, warnings, notes) devtools::build() # build .tar.gz file for distribution
Step 7: Install and Use
devtools::install("C:/R_Projects/mypackage")
library(mypackage)
cv(c(100, 150, 200, 175, 125)) # uses your function
?cv # shows your documentation
Adding Data to Your Package
# Create a dataset
sales_data <- data.frame(month=1:12, revenue=c(42,38,51,55,60,72,68,74,80,78,85,92))
usethis::use_data(sales_data) # saves to data/sales_data.rda
# Add documentation for the dataset in R/data.R:
#' Monthly sales revenue data
#' @format A data frame with 12 rows and 2 columns:
#' \describe{
#' \item{month}{Month number (1-12)}
#' \item{revenue}{Revenue in thousands}
#' }
"sales_data"
Publishing to CRAN or GitHub
# Share via GitHub (easier, no CRAN review required)
usethis::use_github()
# Others install with:
# devtools::install_github("yourusername/mypackage")
# CRAN submission (requires passing devtools::check() with 0 errors/warnings)
# Submit at: https://cran.r-project.org/submit.html
Creating a package forces you to write clean, documented, tested code. Even if you never publish it publicly, packaging your own utility functions and sharing them via GitHub is far better than copying functions between scripts. The devtools and usethis packages make the process much faster than it used to be.
