Quantitative Development and Research-Oriented Systems: R Package Development

This article is part of a series on the design and development of research-grade quantitative software systems, highlighting how software engineering principles improve the scalability, maintainability, and reproducibility of analytical workflows.

In quantitative research, data processing, modeling, and visualization often rely on recurring computational routines. Encapsulating these routines into reusable functions reduces code duplication, improves consistency, and simplifies maintenance.

As projects grow, managing functions through standalone scripts becomes increasingly inefficient. Organizing them into an R package provides a structured framework for code reuse, testing, documentation, version control, and distribution, supporting the development of modular and extensible analytical systems.

The R ecosystem offers a mature set of tools for package development, enabling researchers and quantitative developers to build reusable analytical components following established software engineering practices.

The examples below present a practical workflow for creating and maintaining custom R packages based on my own development experience.

While the exact implementation may vary across projects, the process presented here has proven effective and can serve as a starting point for further refinement.

 Set up the core tools of the R ecosystem: 

These select tools are for the development, documentation, testing and maintenance. 

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

Some times the installation process will return an error associated to dependencies. If this happens, only update it and reinstall the development tools.

install.packages("promises")
update.packages(ask = FALSE)
 
install.packages(c("shiny", "miniUI", "devtools"))

Start, practice, practice and practice:

# //////////////////////////////////////////////////////////////////////////// #
# //////////////////////////////////////////////////////////////////////////// #
# //////////////////////////////////////////////////////////////////////////// #
# //////////////////////////////////////////////////////////////////////////// #

# ------------------------------------------------------------------------------
# CREAR UN PAQUETE DE R
# ------------------------------------------------------------------------------
 
library(devtools)
library(usethis)

# ------------------------------------------------------------------------------
# Crear la estructura base del paquete
create_package("./repo/package_name")

setwd("./repo/package_name")
getwd()

# Configurar tests (crea la estructura)
use_testthat()

# ------------------------------------------------------------------------------
# Crear archivo para funciones de R (R/line_fig.R)
use_r("line_fig")

# Escribir la función en R/line_fig.R con documentación roxygen2
# Ejemplo:
#
# #' Create a line plot
# #'
# #' @param x Numeric vector
# #' @param y Numeric vector
# #' @return A line plot
# #' @export
# line_fig <- function(x, y) {
#   plot(x, y, type = "l")
# }

# ------------------------------------------------------------------------------
# Crear archivo de test (genera un archivo tests/testthat/test-line_fig.R)
use_test("line_fig")

# Ilustracion de un test:
# test_that("line_fig runs without error", {
#   expect_no_error(line_fig(1:10, 1:10))
# })

# ------------------------------------------------------------------------------

# Generar documentación y NAMESPACE
document()

# Ejecutar pruebas
test()

# Revisión completa
check()

# Construir paquete (genera un archivo package_name_1.0.0.tar.gz)
build()

# Instalar paquete localmente
install()
# devtools::install() #desde la carpeta del paquete
# o:
# install.packages("package_name_1.0.0.tar.gz", repos = NULL, type = "source")


# ------------------------------------------------------------------------------

 

# ------------------------------------------------------------------------------
# ACTUALIZATION OF PACKAGES

setwd("./GitHub/package_name")

library(devtools)

# editar funciones y tests
document()
test()
check()
build()

# detach("package:package_name", unload = TRUE)
install()
# update.packages("autoecoreportpk_1.0.tar.gz")

# ------------------------------------------------------------------------------

 Base on my experience, be careful with special characters in .Rd files. Because It could cause fail errors in too many cases.

 And at some point will be relevant start to be implementing the integration of C++ functions in your package (believe me, for experience). 

 The key action that you may have in main are:

 

In practice: 

usethis::create_package("./repo/package_name")
 
# ------------------------------------------------------------------------------
# C++ code and ...
usethis::use_rcpp("package_name")   # creates src/packageName.cpp, .gitignore for .o/.so
usethis::use_mit_license()

# 1-) fallow instruction to paste [code] in R/pckName-package.R
    # BE SECURE TO ADD [#' @importFrom Rcpp evalCpp] if may be needed.
    # and explicit ["_PACKAGE"]
# 2-) write cpp code functions in src/pkgName.cpp

 # you may have to run this before start building the package
Rcpp::compileAttributes()   # writes src/RcppExports.cpp and R/RcppExports.R

# (devtools::document() and devtools::load_all() run this for you.) Never edit
# the RcppExports files by hand — rerun this whenever a C++ signature changes.

# Write the R API with documentation (R/network.R)
# R/filename.R


# ------------------------------------------------------------------------------
# Generar documentación y NAMESPACE
devtools::document() 
#
# ...

 

In practice there are too many issues that you can improve with the integration of C++ in R but the main reference (Chapman & Hall’s) signal three as the key.

 

 

Reference:

Avanced R 

 

Try and improve your learning with algorithms implementations: 

MIT Introduction to Algorithms

Algorithm Libraries - Recomended in Avance R 

Entradas populares

Lo mas consultado

Entradas populares