Search code examples
rr-markdowntidyeval

Evaluate R Markdown Parameters via Quasiquotation & render Function



Hi everyone, thanks for your time.

I have a pretty specific question. I am attempting to programmatically create a PDF document containing multiple graphs and summary tables, all via a single function call. The user will change various parameters in the function, and a new PDF document will be created. The new PDF file will contain various custom graphs, that are created via functions as well.

For example, the user will call the function get_markdown_report(). This function will reference the Rmarkdown file reprex.Rmd. This Rmarkdown file will then reference the function get_count(), which returns a summary table. The end result will be a PDF file containing a summary table, but the end user can define the input data set as well as the grouping variable to create the summary table.

I'm having trouble doing this with the grouping variable. A reproducible example is below.


This is the function definition for get_count(). It takes an input data set and a grouping variable, and returns the number of rows for each value of the grouping variable (such as cut or clarity).

# Loading packages
library(tidyverse)


# Defining function
get_count <- function(data, group_var) {

  # Capturing grouping variable in quosure
  group_var <- enquo(group_var)

  # Determining count of rows per grouping variable
  data %>%
    group_by(!! group_var) %>% 
    summarize(count = n())

}

# Example usage:
# get_count(diamonds, cut)
# get_count(diamonds, clarity)

get_count() is then called within an R markdown file to create a PDF document. Here is the definition of reprex.Rmd:

[Note: I put two backticks instead of three below so that the .Rmd structure would format better.]

---
title: "Reprex"
output: 
  pdf_document:
params: 
  data: data
  group_var: group_var

---

``{r, echo = FALSE, include = FALSE}

## Loading Packages -----------------------------------------------------------

library(tidyverse)
library(rmarkdown)
source("get_count.R")

``

A summary table is printed below:

``{r, echo = FALSE}

group_var <- enquo(params$group_var)

params$data %>%
  get_count(!! group_var)

``

Lastly, this Rmarkdown file will be called from the function get_markdown_report(). The user can define the input dataset and the grouping variable, and a different PDF file will be created.

# Loading packages
library(rmarkdown)

# Defining function
get_markdown_report <- function(data, group_var) {

  # Capturing grouping variable in quosure
  group_var <- enquo(group_var)

  # Rendering PDF markdown document
  render(
    input = "reprex.Rmd",
    params = 
      list(
        data = data, 
        group_var = !! group_var
      )
  )

}

However, Im getting various errors depending on how I structure this, all related to the quotation/tidy evaluation of group_var. The most common error I get is Error: Quosures can only be unquoted within a quasiquotation context..

I'm somewhat familiar with tidy evaluation and quotation, but have never used them before to create a R Markdown document. I think the issue is due to how exactly I reference the grouping variable in either get_markdown_report() or the R Markdown file.

Any suggestions on how to go about this?

Thanks again!


Solution

  • When you are calling render, pass your group_var as a quosure. There is no need to evaluate it, only to have it be immediately re-quoted in the .Rmd.

    In get_markdown_report()

    # Defining function
    get_markdown_report <- function(data, group_var) {
    
      # Capturing grouping variable in quosure
      group_var <- rlang::enquo(group_var)       # <--- Added rlang:: scope resolution
    
      # Rendering PDF markdown document
      render(
        input = "reprex.Rmd",
        params =
          list(
            data = data,
            group_var = group_var                # <--- no !! evaluation, keep as quosure
          )
      )
    
    }
    

    In reprex.Rmd

    I had to switch to using triple back-quote(```) in the .Rmd to get it to render properly:

    ```{r, echo = FALSE}            # <-- I can't get your double `` to render properly
    
    group_var <- params$group_var   # <-- no enquo(), params$group_var is already a quosure
    
    params$data %>%
      get_count(!! group_var)
    
    ```
    

    Testing

    get_markdown_report( mtcars, cyl )    # Works as expected