Skip to Content
Course content

73: R Markdown Parameterized Reports

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

I've seen this happen to almost every developer the first time they try to automate their reporting. You build a beautiful R Markdown report, you set up your parameters in the YAML header, and you run it locally. Everything looks perfect. Then, you try to wrap it in a loop to generate reports for ten different clients, and suddenly, every single PDF comes out with the exact same data—usually the data for the last client you happened to be working on in your console.

The "Global Environment" Ghost

# YAML Header
---
title: "Regional Sales Report"
output: html_document
params:
  region: "North"
---

```{r}
# The bug is hiding right here
sales_data <- read.csv("sales.csv")
filtered_data <- subset(sales_data, region == region)
print(paste("Showing data for:", region))
```

If you ran this in your IDE after manually typing region <- "North" into your console, it would work. You'd see the North region data. But when you try to call rmarkdown::render("report.Rmd", params = list(region = "South")), you'll notice the report still says "North" or, worse, it crashes because region isn't defined in the clean environment where render() runs.

The problem is that R Markdown doesn't magically inject your parameters into the global workspace as standalone variables. It puts them into a specific list called params. In the code above, when R sees region == region, it's comparing the column named "region" to a variable named "region". Since there is no standalone variable named region in the render environment, it either fails or grabs a stale value from your workspace if you're knitting manually.

Accessing the Params List Explicitly

To fix this, you have to be explicit. You aren't looking for a variable called region; you're looking for the region element inside the params list. It's a small syntactic change, but it's the difference between a report that works and one that's useless for automation.

# The corrected code chunk
```{r}
sales_data <- read.csv("sales.csv")

# Use params$region to tell R exactly where the value is coming from
filtered_data <- subset(sales_data, region == params$region)
print(paste("Showing data for:", params$region))
```

Now, when you call render() and pass a list of parameters, R Markdown populates that params object before the code chunks execute. By using the $ operator, you're ensuring the report is actually listening to the instructions you passed it during the render call.

Scaling to Multiple Reports

Once you've stopped fighting with the params list, the real power kicks in. You don't want to manually call render() twenty times. Instead, you can treat your R Markdown file like a function. I usually set up a driver script that iterates through a list of values and spits out a uniquely named file for each one.

# Driver script to automate the reports
regions <- c("North", "South", "East", "West")

for (r in regions) {
  rmarkdown::render(
    input = "regional_report.Rmd",
    params = list(region = r),
    output_file = paste0("Report_", r, ".html")
  )
}

I personally find this approach far superior to copying and pasting the same .Rmd file ten times. If you need to change a plot color or fix a typo in a heading, you change it in one file, and the next time you run your driver script, all ten reports are updated automatically.




📋 Practical Task

Building an Automated Client Portfolio Summary

You have been handed a dataset called client_portfolios.csv with columns client_name, asset_class, and value. Your goal is to create a parameterized reporting system that generates a separate summary for each client.

Requirements:

  • Create an R Markdown file named client_report.Rmd.
  • Define a parameter in the YAML header called client_name with a default value of "Default Client".
  • Inside the R Markdown file, write a code chunk that filters the client_portfolios.csv dataset to only include rows where the client_name column matches the passed parameter.
  • Ensure the report displays a heading (using print() or cat()) that explicitly states: "Portfolio Summary for [Client Name]".
  • Write a separate R script that uses a for loop to render this report for three specific clients: "Alice", "Bob", and "Charlie", saving each as a distinct HTML file (e.g., Alice_Summary.html).
Rating
0 0

There are no comments for now.

to be the first to leave a comment.