Lab 07 - R packages

Learning goals

  • Build an R package.
  • Use Rcpp in the package.
  • Practice your GitHub skills.

Lab description

Today we will write an R package that uses Rcpp. To do so, we will use a template package that has the following set up:

  • Has a single Rcpp function.

  • Uses roxygen2.

  • Uses GitHub Actions for continuous integration.

The R package doesn’t have any testing in place, needs a license, and doesn’t have coverage checking.

Question 1: Make sure you can compile the package

Fork the following repository UofUEpiBio/egpkg, and clone it to your local computer. Once you have a copy, do the following:

  1. Inspect its contents and the file located at .github/workflows.

  2. Make sure you can install it using Rstudio.

  3. Run R CMD check using RStudio.

  4. Run R CMD check using the command line (if available).

If you don’t fork it and instead downloaded it manually, make sure you set up a GitHub repository in your account to push your changes.

Question 2: Adding a plot function

Copy the following R function and add it to the package:

# Here is the function
myplot <- function(x, y) {

  if (!is.numeric(x) | !is.numeric(y)) {
    stop("x and y must be numeric")
  }

  plot(x, y, col = "blue", pch = 19, cex = 2)

  invisible(
   list(
     x = x,
     y = y
   )
  )

}

# Here is an example
set.seed(312)
x <- rnorm(100)
y <- rnorm(100)
myplot(x, y)

Notice that you will need to:

  1. Add it to the R folder.
  2. Document it using roxygen2.
  3. Add the graphics package to the namespace (because of the plot function).
  4. Add an example to the documentation (using the @examples tag).
  5. Add a test for checking that the error message is thrown when the input is not numeric.

Remember to commit and push your changes.

Question 3: Adding a C++ function

Add the ps_match function we wrote on Week 5. The function should be named ps_match:

  1. Add the function in a separate c++ file in the src folder. Make sure to document it using roxygen. Once you finish that, ensure it compiles and the function is visible.1 (then commit and push)
  1. Write an example with artificial data passing a random vector with ten elements distributed U[0, 1]. Add the example to the documentation using the @examples tag. (then commit and push)

  2. Write a test using the testthat R package. The C++ function should match the results of the equivalent R function:

     set.seed(1231)
     x <- cbind(runif(20))
    
     ps_matchR <- function(x) {
    
     match_expected <- dist(x) |> as.matrix()
     diag(match_expected) <- .Machine$integer.max
     indices <- apply(match_expected, 1, which.min)
    
     list(
         match_id = as.integer(unname(indices)),
         match_x  = x[indices]
     )
    
     }

(then commit and push)

Question 4: Checkout the coverage of the package (if time permits)

Using the covr R package, checkout the coverage using the following function

covr::package_coverage()

Footnotes

  1. Remember to run roxygen2::roxygenise(), devtools::document(), or Ctr + Shift + D, if using RStudio.↩︎