devtools::instal_github("jpmonteagudo28/matriz", "jpmonteagudo28/despair","jpmonteagudo28/logos")
what are packages?
R packages are collections of code, data, and documentation that extend R’s functionality beyond its core features. If you have an idea or notice a gap in the existing ecosystem, you can develop a package, test it, document it, and share it with the broader R community. You can distribute your package through the Comprehensive R Archive Network (CRAN)1 (CRAN) or GitHub.
1 CRAN reviews all submitted packages and distributes them as precompiled binaries
how to create a package
All you need (assuming you already know some R) is a solid idea or concept that interests you. Take the time to clarify your idea—what problem does your package solve? How will it be useful? Even if it’s just for you, that’s a great start.
Next, break the problem into steps and outline the primary functions you’ll need. Begin by creating a project folder to serve as the foundation of your package. Your functions will likely evolve as you refine them, but starting with a basic structure will help keep your development process organized.
an intermesso on r projects
Always use RStudio projects! This is just my opinion, but a well-founded one. RStudio projects, combined with the here
and renv
packages, will save you countless headaches. Together, they help keep your code reproducible and shareable in a structured environment.
Also, consider disabling the option to save your workspace on exit. It often leads to unnecessary clutter and can slow things down, especially when working with large datasets. 2
2 How large is “large”? That depends on your RAM.
back to creating packages
Your functions will likely evolve, merge, or be rewritten entirely as your package matures. That’s okay. Most ideas need refinement through trial and error in an isolated environment—your R session—before they’re ready for the world. Stay flexible and be willing to adjust your approach as you develop your package.
To deepen your understanding of package development, you don’t need a Coursera® certificate. Instead, focus on mastering the fundamentals of R programming and, most importantly, read R packages by Hadley Wickham and Jennifer Bryan. It’s short, informative, and packed with insights that will save you time and frustration.
documenting your functions
As you build and modify your functions, document them! Make notes on what each function does, its arguments, and any important details. This will form the basis of your formal documentation later.
One of my favorite shortcuts is using ChatGPT® to generate roxygen2
documentation. I provide a brief explanation of what my function does, a summary of its arguments, and the function code, then ask ChatGPT® to generate the roxygen2
documentation. This saves time—but be warned: ChatGPT® has a habit of “hallucinating,” so always review its output carefully.
write formal tests
While it’s natural to test functions informally in the console, you should also create automated tests to verify their correctness in various scenarios. While I’m not entirely sure if CRAN requires formal tests for all user-facing functions, I totally recommend using the testthat
package to create these automated tests.
regularly check your progress
If it hurts, do more of it. — Joko Willink
Run devtools::check()
regularly throughout the development process. It’s much easier to fix a few small issues as they arise than to deal with a mountain of errors all at once. Frequent checks will make your package better, reduce frustration for the CRAN reviewers, and improve the experience for your future users.
Even if you’re only sharing it on GitHub, always check your package. Your goal should be to provide users with a solid, well-tested, and reliable tool free of logical or implementation errors.
release it to the world
Once you’ve triple-checked (and quadruple-checked) your package and resolved all warnings and notes3, you’re ready to submit to CRAN.
3 Some notes are unavoidable—new packages, for example, always receive a maintainer-related note that can’t be resolved.
Be prepared to communicate with CRAN reviewers and check your email regularly. The submission process can involve some back-and-forth, so try to be patient as you work to get your package on CRAN.
personal experience
What I have described here is based on my personal experience developing R packages. I’ve released three packages to CRAN, despair
,matriz
, and logos
.
The despair
package was a purely fun and silly desire to create (de)motivational quotes and codenames called bard.bits
that could be used as code names.
The matriz
Born out of necessity, this package automates the creation, editing, deletion, and updating of literature matrices and BibTeX references. I built it because my research methods class required us to create literature matrices by hand in Excel®, which was painfully tedious.
The logos
package introduces the writings of the Old and New testament in English, Greek and Hebrew to the R community after realizing they were not available on CRAN or GitHub. 4 I only realized this gap because, in an attempt to do textual analysis on the gospel of John in its original language, I discovered publicly available biblical data was scarce within the R community.
4 the Mormon scriptures have been bundled into a package by Andrew Heiss
I’ve also worked on other packages available on my GitHub profile. Some are still works in progress, but if you’re interested in any of them, you can install devtools and download them directly from GitHub.
Here’s how to install the three packages from CRAN:
install.packages(c("logos","matriz","despair"))
# Downloading packages -------------------------------------------------------
# - Downloading logos from CRAN ... OK [3.2 Mb in 0.77s]
# - Downloading matriz from CRAN ... OK [378.5 Kb in 0.65s]
# - Downloading writexl from CRAN ... OK [198.4 Kb in 0.54s]
# - Downloading despair from CRAN ... OK [113.6 Kb in 0.53s]
# Successfully downloaded 4 packages in 5.7 seconds.
#
# The following package(s) will be installed:
# - despair [0.1.1]
# - logos [0.1.0]
# - matriz [1.0.1]
# - writexl [1.5.1]
# These packages will be installed into "C:/Users/yourname/folder/".
#
# Do you want to proceed? [Y/n]: y
#
# # Installing packages --------------------------------------------------------
# - Installing logos ... OK [installed binary and cached in 0.92s]
# - Installing writexl ... OK [installed binary and cached in 0.57s]
# - Installing matriz ... OK [installed binary and cached in 0.57s]
# - Installing despair ... OK [installed binary and cached in 0.55s]
# Successfully installed 4 packages in 2.8 seconds.
A taste of despair
:
library(despair)
# set a reproducible character seed
sad_seed <- set.char.seed("an ugly horse parade")
# let the demotivation rain
demotivate(cat = "work", seed = sad_seed)
#> [1] "Monday is an awful way to spend 1/7th of your life."
# Let's now boost your ego…perhaps
motivate(cat = "stoic",seed = sad_seed)
#> [1] "Difficulties strengthen the mind, as labor does the body. - Seneca"
# Now come up with a funny Shakesperean code name for a project
bard.bits(cat = "dsm_5", seed = sad_seed)
#> [1] "critical starling"
Here’s the logos package in action:
library(logos)
select_passage("Jhn",chapter = 1,verse = 1:6, language = "English",testament = "new")
#> [1] "In the beginning was the Word, and the Word was with God, and the Word was God." "The same was in the beginning with God." "All things were made through him; and without him was not anything made that hath been made."
#> [4] "In him was life; and the life was the light of men." "And the light shineth in the darkness; and the darkness apprehended it not." "There came a man, sent from God, whose name was John."
# now in Greek
select_passage("Jhn",chapter = 1,verse = 1:6, language = "Greek",testament = "new")
#> [1] "Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος. " "οὗτος ἦν ἐν ἀρχῇ πρὸς τὸν θεόν. " "πάντα διʼ αὐτοῦ ἐγένετο, καὶ χωρὶς αὐτοῦ ἐγένετο οὐδὲ ἕν. ὃ γέγονεν " "ἐν αὐτῷ ζωὴ ἦν, καὶ ἡ ζωὴ ἦν τὸ φῶς τῶν ἀνθρώπων· "
#> [5] "καὶ τὸ φῶς ἐν τῇ σκοτίᾳ φαίνει, καὶ ἡ σκοτία αὐτὸ οὐ κατέλαβεν. " "Ἐγένετο ἄνθρωπος ἀπεσταλμένος παρὰ θεοῦ, ὄνομα αὐτῷ Ἰωάννης· "
Now the matriz package:
library(matriz)
lit_matrix <- init_matrix()
# Get matriz structure to guide in creating records
matriz_names()
#> class
#> year numeric
#> citation character
#> keywords character
#> profession character
#> electronic logical
#> purpose character
#> study_design character
#> outcome_var character
#> predictor_var character
#> sample numeric
#> dropout_rate numeric
#> setting character
#> inclusion_criteria character
#> ethnicity character
#> age numeric
#> sex factor
#> income factor
#> education character
#> measures character
#> analysis character
#> results character
#> limitations character
#> implications character
#> ethical_concerns character
#> biases character
#> notes character
# Start filling out individual record with article info
article <- data.frame(year = 2025,
citation = " ",
keywords = " ",
profession = "underwater basket weaver",
electronic = "YES",
purpose = "To investigate the depth of the oceans and retireve weaving materials",
study_design = "ethnography",
outcome_var = "perceived attitudes towards basket weaving",
predictor_var = NA,
sample = "a small school of clown fish",
setting = "Italy",
drop_rate = 0.13,
inclusion_criteria = "clow fish in Adriatic Sea",
ehtnicity = "oceanic",
age = "0 - 1 year",
sex = "both",
income = " ",
education = "none",
measures = "perceived attitudes",
analysis = "qualitative",
results = "no significant differences",
limitations = "small sample size",
implications = "clow fish don't like humans taking their homes for their own basket weaving endeavors",
ethical_concerns = "no informed consent given to school of clown fish",
biases = "clownfish always try to be funny. Lack of seriounness",
notes = "more research needed")
# Add the record to the literature matrix
lit_matrix <- add_record(lit_matrix, article, .before = 1)
# Update record if mistake was made
lit_matrix <- update_record(lit_matrix, notes, where = year == 2025, set_to = "actually, the clow fish don't want us to come back.")