Search code examples
rggplot2yamlquarto

ggplot are all the same when yaml parameter is passed and quarto_render is used in loop


I want to render multiple html documents using quarto_render

I have a main.qmd containing:

library(quarto)
library(glue)

# List of IDs of interest
ids <- c("A", "B", "C")

# Generate individual reports
sapply(ids, function(id) {
    quarto_render(
            input = "test.qmd",
            output_format = "html",
            output_file = glue("report_{id}.html"),
            execute_params = list(ID = id),
            debug = TRUE
    )
})

within test.qmd I filter the dataframe using the ID value and then plot the filtered data.frame

---
params:
  ID: null
---
```{r}
# Load packages
library(tidyverse)
``` {r r params$ID}

L3 <- LETTERS[1:3]
char <- sample(L3, 12, replace = TRUE)
df <- data.frame(x = 1, y = 1:12, char = char)

df_test <- df %>%
    filter(char == params$ID)
print(params$ID)
print(df_test)

ggplot(df_test, aes(x = x, y = y)) +
    geom_point()```

Although print(params$ID), print(df_test) look correct. The plots are all the same and reflect the points of char==C.

Does it have to do with the saved .png file that apparently gets overwritten before the documents are created?


Solution

  • This is happening because your HTML reports point to the same folder with shared resources, including the same plot for all three reports. This could be solved if somehow the chunk name changed for every report, but there is a better way.

    You can setup Quarto so that your reports are created as self-contained HTML files, which are HTML files that contain all resources required for rendering within the same .html file, no external folders involved. This produces files that are a little heavier, but are more portable, i.e., don't require a "files" folder to render properly.

    Change your YAML to the following in order to get reports with embedded-resources, thus self-contained. This way, all reports will point to their own internal resources, such as plots, instead of trying to read them from an external folder:

    ---
    params:
      ID: null
    format: 
      html:
        embed-resources: true
    ---
    

    Your execution script should be as follows:

    library(quarto)
    library(glue)
    
    # List of IDs of interest
    ids <- c("A", "B", "C")
    
    # Generate individual reports
    sapply(ids, function(id) {
        quarto_render(
            input = "test.qmd",
            output_file = glue("report_{id}.html"),
            execute_params = list(ID = id),
        )
    })