Skip to Content
Course content

69: Writing Roxygen2 Documentation

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent a fair amount of time building R packages, and for the longest time, I absolutely hated the documentation phase. I used to think it was a separate chore—something you did at the very end after the code was "finished." But the problem with that approach is that by the time you get to the man/ folder to write those arcane .Rd files, you've forgotten why you added that one weird edge-case check in line 42.

The "Where is the Help File?" Problem

Let's look at a function I just wrote for a project. It's a utility to clean up currency strings (like "$1,200.50") and turn them into actual numbers so we can do math with them. Here it is:

parse_currency <- function(x) {
  x <- gsub("[$,]", "", x)
  as.numeric(x)
}

Now, if I'm using this in a package, I expect to be able to type ?parse_currency to remember exactly how it handles commas or nulls. But when I try that right now, R just tells me No documentation for ‘parse_currency’ in R. Of course it does; I haven't told R how to describe it. Now, I could manually create a file in the man/ directory using LaTeX-style syntax, but that's a fast track to a headache. I'd rather stay in my code.

Trying the Roxygen approach

This is where roxygen2 comes in. The idea is that we write the documentation above the function using special comments starting with #'. I'll try adding a basic description and defining the parameters.

#' Convert currency strings to numeric
#' 
#' This function removes dollar signs and commas from a character vector.
#' 
#' @param x A character vector containing currency strings.
#' @return A numeric vector.
#' @export
parse_currency <- function(x) {
  x <- gsub("[$,]", "", x)
  as.numeric(x)
}

I've added the @param tag to describe the input and @return to describe the output. I also threw in @export, which is a crucial bit of shorthand telling R that this function should be available to the user of the package, not just kept as an internal helper. Now, I'll try ?parse_currency again. Still nothing. Why?

The missing bridge

I forgot the most important part of the workflow: Roxygen comments are just comments until they are processed. They don't magically turn into help files just by existing. I need to trigger the tool that reads these comments and generates the actual .Rd files that R understands.

I'll run this command in my console:

devtools::document()

If you look at your file explorer now, you'll see that roxygen2 has automatically created a file called parse_currency.Rd inside the man/ folder. I didn't have to touch a single line of that ugly markup. Now, when I run ?parse_currency, the help pane pops up exactly as expected. It's a much cleaner loop: write code, document it right there, and run one command to sync everything.

Adding a bit more flavor

The basic description is fine, but users usually want to see the function in action. I'll add an @examples section. I'll also add a @details section for when I need to explain the "why" behind a certain implementation choice—like the fact that this function assumes the currency is US-based.

#' Convert currency strings to numeric
#' 
#' @param x A character vector containing currency strings.
#' @return A numeric vector.
#' 
#' @details This function specifically targets US-style formatting (dollar signs 
#' and commas). It will return NA for strings that cannot be coerced to numeric.
#' 
#' @examples
#' parse_currency("$1,200.50")
#' parse_currency(c("$10", "$20.50"))
#' @export
parse_currency <- function(x) {
  x <- gsub("[$,]", "", x)
  as.numeric(x)
}

Again, I run devtools::document(), and the help file updates instantly. One thing I've learned the hard way: if you change the arguments of your function (say, you add a decimal_mark argument), your @param tags are now lying to your users. Make it a habit to update the Roxygen block in the same breath you update the function signature.




📋 Practical Task

Documenting the Signal-to-Noise Ratio Function

You have been handed a function that calculates the Signal-to-Noise Ratio (SNR) for a dataset, but it has zero documentation. Your task is to make it "package-ready" using roxygen2.

The Code:

calculate_snr <- function(signal, noise) {
  if (any(noise == 0)) {
    stop("Noise cannot contain zeros.")
  }
  return(mean(signal) / mean(noise))
}

Requirements:

  • Add a concise title and a brief description of what the function does.
  • Use @param to document both signal and noise (assume both are numeric vectors).
  • Use @return to explain that the result is a single numeric value.
  • Use @export so the function is accessible to users.
  • Add an @examples section showing a successful calculation with two small numeric vectors.

Once you've written the block, describe (or simulate) the command you would run to generate the actual .Rd help file.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.