Examples of Creating and Using R Packages: 3 Practical Examples for Real Projects

If you write more than a few R scripts a month, you should be thinking about packages. The best way to learn is by looking at concrete examples of creating and using R packages: 3 practical examples that mirror the kind of work analysts, data scientists, and researchers actually do. Instead of abstract theory, we’ll walk through real examples of packaging your own functions, documenting them, testing them, and sharing them with your team. In this guide, we’ll start with a tiny utility package, move to a data analysis helper package, and finish with an API client package that talks to a web service. Along the way, you’ll see examples of how to structure an R package, how to use modern tools like `usethis`, `devtools`, and `testthat`, and how to avoid the most common mistakes that make packages painful to maintain. If you’ve ever copy‑pasted the same R function into three different projects, this article is written for you.
Written by
Jamie
Published
Updated

Most R users start with loose scripts: analysis_final.R, analysis_final2.R, and the dreaded analysis_final_really_final.R. The turning point is when you realize that the same functions keep showing up everywhere. That’s where packages come in.

This article focuses on examples of creating and using R packages: 3 practical examples that map directly to real work:

  • a small utility package for data cleaning
  • a reusable analysis toolkit for a specific domain
  • an API client package that wraps a web service

Along the way, we’ll sprinkle in more real examples, like internal company packages, teaching packages for courses, and research reproducibility packages. The goal is not to memorize package anatomy, but to see how packages solve everyday problems.

Tooling note: everything here assumes a modern R workflow with R 4.3+, RStudio or Posit Workbench, and the tidyverse/devtools/usethis ecosystem.


Example 1: A tiny utility package that replaces copy‑paste

Let’s start with the most common example of creating and using R packages: you have a handful of helper functions that live in a scratch script and you keep reusing them across projects.

Imagine you work in analytics and repeatedly need to:

  • standardize column names
  • parse messy date columns
  • quickly inspect missing values

Instead of copy‑pasting these helpers, you turn them into a package called datacleanr.

Step 1: Create the package skeleton

In an interactive R session:

install.packages(c("usethis", "devtools"))

usethis::create_package("~/projects/datacleanr")

This sets up a minimal package structure:

datacleanr/
  DESCRIPTION
  NAMESPACE
  R/
  man/

You now have your first real example of using R packages: you can open this folder in RStudio and R recognizes it as a package project.

Step 2: Add a simple function

Create R/clean_names.R:

#' Clean column names in a data frame
#'
#' Converts column names to snake_case, removes special
#' characters, and trims whitespace.
#'
#' @param x A data.frame or tibble.
#'
#' @return An object of the same class as `x` with cleaned names.
#' @export
#'
#' @examples
#' df <- data.frame("First Name" = 1:3, "Last.Name" = 4:6)
#' clean_names(df)
clean_names <- function(x) {
  nm <- names(x)
  nm <- gsub("[^A-Za-z0-9_]+", "_", nm)
  nm <- gsub("([a-z0-9])([A-Z])", "\\1_\\2", nm)
  nm <- tolower(nm)
  nm <- gsub("_+", "_", nm)
  nm <- gsub("^_|_$", "", nm)
  names(x) <- nm
  x
}

Those comment lines starting with #' are roxygen2 documentation. They become help pages when you build the package.

Step 3: Document and load your package

Run:

devtools::document()   # generates NAMESPACE and man/*.Rd
devtools::load_all()   # load package as if installed

Now in the same R session:

library(datacleanr)

mtcars2 <- mtcars
names(mtcars2) <- c("Miles per Gallon", names(mtcars2)[-1])

cleaned <- clean_names(mtcars2)
names(cleaned)
#> [1] "miles_per_gallon" "cyl" "disp" ...

You’ve just created and used your own R package locally. This is one of the simplest examples of creating and using R packages: 3 practical examples will build on this pattern, but the workflow is the same.

Step 4: Add tests so you trust your helpers

Testing is where packages start to feel serious.

usethis::use_testthat()
usethis::use_test("clean_names")

Edit tests/testthat/test-clean_names.R:

test_that("clean_names works on simple names", {
  df <- data.frame("First Name" = 1:3, "Last.Name" = 4:6)
  out <- clean_names(df)
  expect_equal(names(out), c("first_name", "last_name"))
})

Run:

devtools::test()

Now every time you tweak clean_names(), devtools::test() tells you whether you broke anything. This is a small but powerful example of using R packages as a safety net for your own work.


Example 2: A domain-specific analysis toolkit as an R package

The next step up in complexity is an internal package that encapsulates a full workflow. Among the best examples of creating and using R packages in real organizations are these domain-specific toolkits.

Imagine you work in public health and repeatedly run the same type of analysis on surveillance data. A package called epiToolsR might:

  • import CSVs from a secure server
  • apply standard cleaning rules
  • calculate incidence rates
  • generate ggplot2-based summary charts

This is no longer just one helper; it’s an opinionated workflow in a package.

Example functions in a domain package

Inside R/, you might have:

#' Import and standardize surveillance data
#' @param path File path to CSV export.
#' @export
import_surveillance <- function(path) {
  raw <- read.csv(path, stringsAsFactors = FALSE)
  raw\(date <- as.Date(raw\)date)
  raw\(age_group <- factor(raw\)age_group,
                          levels = c("0-17", "18-49", "50-64", "65+"))
  raw
}

#' Calculate weekly incidence per 100,000
#' @param data Data frame from import_surveillance().
#' @param population Named vector of population counts.
#' @export
weekly_incidence <- function(data, population) {
  agg <- aggregate(cases ~ week + age_group, data, sum)
  agg\(incidence <- 1e5 * agg\)cases / population[agg$age_group]
  agg
}

You might also include a standard plot:

#' Plot weekly incidence by age group
#' @export
plot_weekly_incidence <- function(inc_data) {
  ggplot2::ggplot(inc_data, ggplot2::aes(week, incidence, color = age_group)) +
    ggplot2::geom_line() +
    ggplot2::labs(y = "Incidence per 100,000", x = "Week")
}

Using the package in real workflows

In your analysis projects, the script becomes dramatically shorter:

library(epiToolsR)

pop <- c("0-17" = 73000000, "18-49" = 138000000,
         "50-64" = 63000000, "65+" = 54000000)

dat <- import_surveillance("data/export_2024w10.csv")
inc <- weekly_incidence(dat, pop)
plot_weekly_incidence(inc)

This is one of the best examples of how packaging your workflow:

  • reduces copy‑paste
  • encodes organizational standards
  • makes onboarding new analysts much easier

Public health is just one domain. Other real examples include:

  • a finance package that standardizes portfolio performance calculations
  • a marketing analytics package that wraps attribution models
  • a clinical research package that enforces consistent table shells for publications

For inspiration, look at how established packages organize domain logic. CRAN’s Task Views (e.g., Epidemiology, Finance) at https://cran.r-project.org/web/views/ show curated lists of real-world packages.


Example 3: An API client package that talks to a web service

The third of our examples of creating and using R packages: 3 practical examples is an API client. This is increasingly common in 2024–2025 as more data lives behind web APIs.

Suppose you need to fetch data from a public health API every day. Instead of sprinkling raw httr calls in your scripts, you wrap the logic in a package called healthapiR.

Core API wrapper function

#' Get time series data from the health API
#'
#' @param endpoint API endpoint, e.g. "cases" or "hospitalizations".
#' @param start,end Date range.
#' @param api_key Optional API key for authenticated endpoints.
#' @export
get_timeseries <- function(endpoint, start, end, api_key = Sys.getenv("HEALTH_API_KEY")) {
  base <- "https://api.examplehealth.org/v1"
  url <- sprintf("%s/%s", base, endpoint)

  resp <- httr::GET(
    url,
    httr::add_headers(Authorization = paste("Bearer", api_key)),
    query = list(start = start, end = end)
  )

  httr::stop_for_status(resp)
  out <- httr::content(resp, as = "parsed", type = "application/json")
  tibble::as_tibble(out$data)
}

You might add helpers for specific endpoints:

#' Daily case counts by state
#' @export
get_daily_cases <- function(start, end) {
  get_timeseries("cases", start, end)
}

#' Hospital occupancy by state
#' @export
get_hospital_occupancy <- function(start, end) {
  get_timeseries("hospital_occupancy", start, end)
}

Using the API client package

In your dashboard or report script, you now write:

library(healthapiR)

cases <- get_daily_cases("2024-01-01", "2024-03-31")
occ   <- get_hospital_occupancy("2024-01-01", "2024-03-31")

Instead of:

  • building URLs by hand
  • remembering query parameters
  • re-implementing error handling in every script

This sort of API client is one of the clearest real examples of creating and using R packages in modern data teams. It also plays nicely with reproducible research practices recommended by organizations like the National Institutes of Health and the Centers for Disease Control and Prevention, where consistent, documented data access is a big deal.


Beyond the 3 core examples: more ways R packages show up in practice

Although this article centers on examples of creating and using R packages: 3 practical examples, real life rarely stops at three. Once you understand the pattern, you start seeing packages everywhere. Some additional examples include:

  • Internal utility packages that bundle company color palettes, ggplot2 themes, and slide templates
  • Teaching packages for university courses that ship datasets, exercises, and grading helpers
  • Research packages that accompany academic papers, providing code and functions to reproduce figures and tables
  • Model packages that wrap trained models (e.g., predict_model() functions) so they can be used consistently across products

If you’re teaching R, a teaching package might include:

#' Grade a student's regression assignment
#' @param model A fitted lm() object.
#' @export
grade_regression <- function(model) {
  if (!inherits(model, "lm")) {
    stop("model must be an lm object")
  }
  r2 <- summary(model)$r.squared
  if (r2 > 0.9) return("A")
  if (r2 > 0.8) return("B")
  if (r2 > 0.7) return("C")
  "D"
}

This is another concrete example of using R packages to standardize logic across multiple assignments or cohorts.

For reproducible research, the Harvard Data Science Initiative and similar academic groups often encourage packaging analysis code so that others can install and run it with a single command, rather than chasing down scripts.


If you’re looking for up-to-date examples of creating and using R packages, it helps to know what’s changed recently:

  • R 4.3+ has better performance and improved base tools, which you should target for new packages.
  • pak and renv are now standard in many teams for dependency management and reproducible environments.
  • GitHub Actions is widely used for continuous integration, running R CMD check and tests on every push.
  • Posit (formerly RStudio) continues to invest in package tooling like devtools, usethis, and testthat, which are the backbone of the examples in this article.

When you look for real examples of creating and using R packages, check:

  • the tidyverse packages (e.g., dplyr, ggplot2) for design patterns
  • the rOpenSci ecosystem (https://ropensci.org/) for high-quality API client packages

Studying these projects gives you concrete, production-grade examples of how packages are structured, tested, and documented.


Putting it all together: picking your first package project

If you’re wondering where to start, the best examples are the ones that hurt you today:

  • Do you copy the same 5–10 helper functions into every new project? That’s your utility package.
  • Do you repeat the same data-cleaning and plotting workflow for each new dataset in your domain? That’s your domain toolkit package.
  • Do you hit the same API with slightly different scripts? That’s your API client package.

Each of these is an example of creating and using R packages that pays off within weeks, not months. You don’t need to publish to CRAN to get value; an internal Git repository is enough.

A minimal starting workflow looks like this:

usethis::create_package("~/projects/myfirstpkg")

## Add your first function in R/
## Document and load
devtools::document()
devtools::load_all()

## Add tests
devtools::test()

## Install locally
devtools::install()

From there, you can grow the package as needs arise, just like in the three practical examples we covered.


FAQ: common questions about R package examples

What are some simple examples of creating and using R packages for beginners?

Some easy starting points:

  • a package with one or two data-cleaning helpers you already use
  • a package that ships a small dataset plus one plotting function
  • a package that wraps a single API endpoint you call frequently

These are all small-scale examples of creating and using R packages that teach you the full workflow without being overwhelming.

Do I need to publish to CRAN to use my own package?

No. Most real examples of R package usage in companies never touch CRAN. You can:

  • install from a local folder with devtools::install()
  • install from GitHub with remotes::install_github("org/pkg")
  • use internal package repositories or artifact storage

CRAN is great for public packages, but internal packages are where many of the best examples live.

Can I turn an existing project into an example of an R package?

Yes, and it’s often easier than starting from scratch. Identify the parts of your project that are reusable (functions, data access code, plotting templates) and move them into R/ files in a new package. Your original analysis scripts then import and call those functions, just like in the three practical examples in this article.

Where can I find high-quality real examples of R packages to learn from?

Good places to look:

  • CRAN Task Views for your domain
  • tidyverse packages on GitHub
  • rOpenSci packages, especially API clients

These are full, production-grade examples of creating and using R packages, with testing, documentation, and real user communities.


The bottom line: the most useful examples of creating and using R packages: 3 practical examples aren’t theoretical. They’re the small, targeted packages that remove friction from your day-to-day work. Start with one pain point, package it, and let the tooling do the rest.

Explore More R Code Snippets

Discover more examples and insights in this category.

View All R Code Snippets