1

I am documenting many data frames in an R package, either because they are returned by a function or they are included as data. Oftentimes, the same column/item needs to be described for many data frames. How can I avoid copy/pasting the same item description multiple times?

For example, imagine I am documenting the following data frames in R/data.R:

#' @name OBJ_1
#' @title Object 1
#' @format A data frame with 401 rows and 6 variables:
#' \describe{
#'   \item{\code{feature_ID}}{character, a very carefully defined description}
#'   \item{\code{col1}}{double, blah}
#'   \item{\code{col2}}{integer, blah}
#'   \item{\code{col3}}{character, blah}
#'   \item{\code{col4}}{integer, blah}
#'   \item{\code{col5}}{character, blah}
#'}   
"OBJ_1"

#' @name OBJ_2
#' @title Object 2
#' @format A data frame with 333 rows and 5 variables:
#' \describe{
#'   \item{\code{feature_ID}}{character, a very carefully defined description}
#'   \item{\code{col6}}{double, blah}
#'   \item{\code{col7}}{integer, blah}
#'   \item{\code{col8}}{character, blah}
#'   \item{\code{col9}}{integer, blah}
#'}   
"OBJ_2"

And similarly I want to document a data frame returned by a function:

#' Some function 
#'
#' @return data frame with one row per feature:
#' \describe{
#'   \item{\code{feature_ID}}{character, a very carefully defined description}
#'   \item{\code{colx}}{blah}
#'   \item{\code{coly}}{blah}
#' }
#' 
#' @export
#' 
myFunction = function(){
  # do stuff
  return(df)
}

In all three cases, feature_ID is defined the same way. Is there any way to define feature_ID somewhere once and use an expression in Roxygen that is evaluated to insert the desired definition in the .Rd docs?

@eval is a nice way to do this for repeated @params, but @eval does not work inside another Roxygen tag like @format or @describe.

I also tried the dynamic R code solution, but this:

feature_ID = function(){
  "character, a very carefully defined description"
}
...
#'   \item{\code{feature_ID}}{`r feature_ID()`}

was evaluated to this in the corresponding .Rd:

\item{\code{feature_ID}character, a very carefully defined description)`}

instead of:

\item{\code{feature_ID}{character, a very carefully defined description}

...which seems like a bug more than any intended behavior...

From this, it sounds like @templateVar name value is promising, but I can't find any documentation about how to actually implement this.

I'd appreciate any help! Lots of copy/paste feels like a sin and would be horribly inefficient if/when we end up wanting to change the definition of a variable.

larenite
  • 217
  • 1
  • 9

1 Answers1

1

It turns out the behavior described using the dynamic R code solution was a bug. I was using roxygen2 version 7.1.2. Updating to version 7.2.1 resolved the issue and gave me the solution I wanted.

Here's a complete example of how to dynamically insert text into Roxygen documentation upon rendering.

  1. Define frequently used arguments/params/items in an R script, something like R/define_params.R. You don't need to add Roxygen tags, or if you do, add @noRd and do not include @export so that the function is not exported and a corresponding .Rd is not generated.
    feature_ID = function(){
      "character, a very carefully defined description"
    }
    
    assay = function(){
      "character, another description I use a lot"
    }
    
  2. Use dynamic R code to insert the string(s) in Roxygen documentation, including inside tags.
    #' Some function 
    #'
    #' @return data frame with one row per feature:
    #' \describe{
    #'   \item{\code{feature_ID}}{`r feature_ID()`}
    #'   \item{\code{colx}}{blah}
    #'   \item{\code{coly}}{blah}
    #' }
    #' 
    #' @export
    #' 
    myFunction = function(){
      # do stuff
      return(df)
    }
    
    #' @name OBJ_1
    #' @title Object 1
    #' @format A data frame with 401 rows and 7 variables:
    #' \describe{
    #'   \item{\code{feature_ID}}{`r feature_ID()`}
    #'   \item{\code{assay}}{`r assay()`}
    #'   \item{\code{col1}}{double, blah}
    #'   \item{\code{col2}}{integer, blah}
    #'   \item{\code{col3}}{character, blah}
    #'   \item{\code{col4}}{integer, blah}
    #'   \item{\code{col5}}{character, blah}
    #'}   
    "OBJ_1"
    
  3. Generate the docs using roxygen2::roxygenise()
  4. If you look at the .Rd files, you will see that your R code was replaced with the strings defined in the corresponding functions, e.g.:
    ...
    \item{\code{feature}}{character, a very carefully defined description}
    \item{\code{assay}}{character, another description I use a lot}}
    ...
    
larenite
  • 217
  • 1
  • 9