Imagine that you are a healthcare worker, and you are working on automating the next clinic day or the last clinic day of a patient based on:
You’d like to get a response that looks like this:
“Your next clinic day is Saturday, 04 September 2021” or “Your last clinic day was Monday, 30th August 2021”
You have worked out the codes required and captured them into three functions shown below:
## Print date stamp as desired
date_stamp <- function(date) {
date <- as.Date(date)
format(date, "%A, %d %B %Y")
}
## last clinic appointment
appt_last <- function(c_date = Sys.Date(), d_pills, days = NULL) {
c_date <- as.Date(c_date)
dt <- if (is.null(days)) {
date_stamp(c_date - as.integer(d_pills))
} else {
date_stamp(c_date - as.integer(days))
}
cat("Your last clinic appointment was on", dt, sep = " ")
}
## next clinic appointment
appt_next <- function(c_date = Sys.Date(), d_pills, days = NULL) {
c_date <- as.Date(c_date)
dt <- if (is.null(days)) {
date_stamp(c_date + as.integer(d_pills))
} else {
date_stamp(c_date + as.integer(days))
}
cat("Your next clinic appointment is on", dt, sep = " ")
}
Having being part of the satuRday NairobiR conference, you have decided to develop these functions into a package. You have a colleague who has decided to walk you through the process of the package development. The steps involved are as below:
Step 1: Decide on the name you’d like to call your package (keep it simple and short)
Step 2: Check that the name is not already in used (on CRAN, GitHub and Bioconductor), and also the sentiment
available::available("my-pkg-name")
Step 3: When you have decided on a package name that is not already in use, create a package directory
library(devtools)
path <- "path-to-my-pkg/my-pkg-name"
create_package(path)
A new RStudio containing your project will open. The package folder should have the followings (you might have to click on “more” option in the “file” browser, then toggle on “show Hidden files”):
.gitignore
.Rbuildignore
pkg-name.Rproj
DESCRIPTION
NAMESPACE
R
.Rproj.user/
Step 4: Put your first function in new R scripts.
use_r("function-name")
The function above automatically creates a script in the R directory with the function name you have assigned.
Step 5: optimize your function for package development
## Print date stamp as desired
date_stamp <- function(date) {
date <- lubridate::as_date(date)
base::format(date, "%A, %d %B %Y")
}
Next, we will be iterating through load_all()
and check()
functions. load()
makes our function available to be used in the console, while check()
“checks” the status of our package development.
Step 6: load your function, and try it out
load_all()
date_stamp("2021-09-03")
date_stamp(Sys.Date())
We are making steady progress…
Step 7: Check package status
check()
Notice that you have two “warnings” already being displayed. But what did you do wrong? RStudio gives you more info by letting you know that one of the warnings is from licensing while the other one relates to the {lubridate} package. We will address these in a bit.
Step 8: modify the DESCRIPTION metadata. We will show example of two authors.
Title: Appointment Scheduling System for Patients # one line, sentence format
Authors@R:
c(person(given = "Stephen",
family = "Balogun",
role = c("aut", "cre"),
email = "stephentaiyebalogun@gmail.com",
comment = c(ORCID = "0000-0002-9928-3703")),
person(given = "Shelmith",
family = "Kariuki",
role = "aut",
email = "shelmith.kariuki@gmail.com",
comment = c(ORCID = "0000-0002-2444-4226")))
Description: An easy, concise and reliable way of scheduling appointment for patients based on their clinic date,
number of pills dispensed and/or number of days of appointment given.
Step 9: Pick a license for your package. Common ones are MIT + file license, GPL (GPL-2, GPL-3), CCO, CCBY. You can also use proprietary license.
use_mit_license("firstname Lastname")
Step 10: check your package again
check()
Notice that one of the “warnings” previously received has been addressed.
Step 11: write the documentation for your function. These are stored in the “man” folder (man/)
click anywhere in your script, then click on the “Code” tab, “Insert roxygen skeleton” and update accordingly
convert your roxygen code to function documentation
document() ## this also exports your function to the NAMESPACE file
Observe the changes in the NAMESPACE file.
Step 12: import all the functions from other packages used in creating your own function (aside pre-shipped R packages)
use_package("lubridate") ## run 'check()' to be sure that the second warning has been removed
Also include the packages as imports in the function. “@import pkg-name” or “@importFrom pkg-name pkg-function”. Observe the changes in the DESCRIPTION file.
Step 13: Now, we can install our package locally with the “install()” or using the “install and restart” button from the “build” pane
install()
Step 14: next is unit testing. First, we declare our intent to write unit tests and to use the testthat package for this, thereafter, we write the “test” for our function(s)
use_testthat()
## write the unit test
use_test("function-name")
## in the R script, insert
test_that("date_stamp is consistent", {
expect_identical(
date_stamp(Sys.Date()),
format(Sys.Date(), format = "%A, %d %B %Y")
)
})
Step 15: It’s time to connect to git to manage your package development. Run “check()” again to be sure that all is set for deployment.
use_git() ## this creates a ".git" folder
You will be asked if you’d like to commit your codes and restart the computer.
Step 16: now that you have a (basic) functional package, deploy this to GitHub
use_github()
Step 17: document your package in a markdown document
use_readme_rmd()
## edit your markdown, then build
build_readme()
Step 18: Commit and push your files to GitHub
Step 19: Iterate through the processes from step 4 to step 18 using the other functions.
Step 20: Install your package from GitHub
remotes::install_github("github-acct/package-name")
Step 21: write your vignette(s)
use_vignette("vignette-name", "Vignette Title")
Modify the template appropriately, then build your vignette.
build_vignettes()
Iterate if you are writing more than one vignette.
Step 22: “check” your package again
check()
Notice that this introduces a “warning” on Windows OS - “‘qpdf’ is needed for checks on size reduction of PDFs”. You need a application to compress the pdf vignette generated. Follow the steps below to resolve this:
Download qpdf for windows from https://sourceforge.net/projects/qpdf/?source=typ_redirect
Unzip the downloaded document
Copy the extracted qpdf (qpdf-major-minor-patch) to a directory in C:/Program Files
In R, run Sys.setenv(‘PATH’ = paste0(‘C:/Program Files/qpdf-version_numer/bin;’, Sys.getenv(‘PATH’))). One further step may be required to convince Windows that pqdf is safe to run. Navigate to “C:/Program Files/qpdf-version_numer/bin” and execute qpdf.exe
(by double-clicking). You’ll need to use the more options link to find the button to run the program.
Run “check()” again.
use_news_md()
and modify appropriately.release()
.submit_cran()
to avoid walking through the other steps.