Customize knit button; access yaml params

In my R Markdown document, I have successfully overridden the Knit button behavior using the examples posted at https://bookdown.org/yihui/rmarkdown-cookbook/custom-knit.html. I understand that the custom knit function itself doesn't take any arguments other than 'input', but I'm wondering if there is a way to access a params value set earlier in the yaml of the R Markdown document?

Here's a simplified example--ideally, I would purrr::walk() across a character vector of regions set in the params and render each region to a different output file.

---
params:
  regions: !r c('county','city')
output: html_document
knit: (function(input, ...) {
  purrr::walk(
    .x = params$regions,
    .f = ~ rmarkdown::render(
               input,
               output_file = paste0(xfun::sans_ext(input), '_', .x, '.html'),
               envir = globalenv()
           )
    )
  })
---

When I try to knit this example, I get this error:

Error in map(.x, .f, ...) : object 'params' not found
Calls: <Anonymous> -> <Anonymous> -> map
Execution halted

Thank you for any help you can provide!

1 Like

Wow ! This is an interesting use case !

I understand you want the knit button of the RStudio IDE to generate multiple parametrized report, is that correct ? I am not sure because you are not passing .x as a params in render() :thinking:

Anyway, I don't think currently this is possible to access this params field as the error shows. I believe this is because the code you put in the knit field is executed by the RStudio IDE (not by rmarkdown) and when evaluating this code, the IDE may not now about the params field, or at least did not evaluated it as params. IMO, this would be a feature request for the IDE.

Usually, for this kind of task, I use a main R script called _render.R thant contains your code with purrr::walk

input <- 'my_rmd_file.Rmd'
purrr::walk(
    .x = c('county','city'),
    .f = ~ rmarkdown::render(
               input,
               output_file = paste0(xfun::sans_ext(input), '_', .x, '.html'),
               params = list(regions = .x)
           )
    )

And if I want it to be run by the knit button, I make the script taking an argument and sourced the script (using xfun::Rscript() for example) with a function in knit: field.

Thank you for thinking about this, @cderv! It sounds like this isn't doable exactly how I envisioned. Because running the report for several hundred cities/towns/schools is quite time-consuming (and usually not needed), I typically only want to generate region and/or county reports.

Here is how I'm dealing with it in the near-term:

  1. custom package that provides this alternative knit behavior:
knit_all_geographies <- function(input, ...) {
  # geo_types is a list of all possible geographies for which to generate
  # an individual report
  geo_types <- c('region','county','city','town','school')
  purrr::walk(
    .x = geo_types,
    .f = ~ rmarkdown::render(
              input,
              output_file = paste0(xfun::sans_ext(input), '_', .x, '.html'),
              params = list(geo_type = .x),
              envir = globalenv()
          )
  )
}
  1. Front matter in my RMD that includes this:
---
params: 
# list of geo_types to render; some/all of: region, county, city, town, school
  render_geo_types:
    - region
    - county
# leave this blank; the custom knit function will purrr::walk over this
  geo_type: ''
knit: ptmknit::knit_all_geographies # call to custom knit 
---
  1. A chunk in my RMD document that checks to see whether the current parameterized params$geo_type is in params$render_geo_types. If not, write a short message and quit knitting that particular geography (though the output file is still generated).
# check to see if the paramterized 'geo_type' is in the 'render_geo_types'
# vector. if not, exit knitting.
if (!(params$geo_type %in% params$render_geo_types)) {
  pander::pandoc.p('Report not generated for this geography.')
  knitr::knit_exit()
}
1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.