Examples of Creating and Using R Packages: 3 Practical Examples for Real Projects
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.
Modern trends (2024–2025) in R package development
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.
pakandrenvare now standard in many teams for dependency management and reproducible environments.- GitHub Actions is widely used for continuous integration, running
R CMD checkand tests on every push. - Posit (formerly RStudio) continues to invest in package tooling like
devtools,usethis, andtestthat, 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.
Related Topics
Practical examples of loops and conditional statements in R
Practical R code examples of examples of reading and writing CSV files
Examples of Creating and Using R Packages: 3 Practical Examples for Real Projects
Real‑world examples of top examples of connecting to databases with R
Examples of data manipulation with dplyr: 3 practical examples
Explore More R Code Snippets
Discover more examples and insights in this category.
View All R Code Snippets