rmarkdown does not render PDFs as batch

This is a cross-post from StackOverflow where no solution is provided.

I have a rmarkdown file that renders well in RStudio with the Knitr button or with rmarkdown() but does not render when rendered as part of a batch with purrr::walk() and being passed a parameter. The batch issue only occurs when fig.show="hold", out.width="50%" is included in a section of the rmarkdown file.

library(purrr)
library(tinytex)
SurveySet <- c(20,19,68,79,30,18,42)
purrr::walk(
  .x = SurveySet,
  ~ rmarkdown::render(
    input = "Test.Rmd",
    output_file = glue::glue("REPORTS/Report Fails {.x}.pdf"),
    params = list(Unit = {.x})
  )
)
purrr::walk(
  .x = SurveySet,
  ~ rmarkdown::render(
    input = "TestWorks.Rmd",
    output_file = glue::glue("REPORTS/Report Works {.x}.pdf"),
    params = list(Unit = {.x})
  )
)

Test.Rmd as

---
title: "`r params$Unit`"
output: pdf_document
params:
  Unit: 68
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```

## R Markdown
This Document renders with RStudio Knitr button but not with batch

```{r figures-side, fig.show="hold", out.width="50%"}
par(mar = c(4, 4, .1, .1))
plot(cars)
plot(mpg ~ hp, data = mtcars, pch = 19)
```

TestWorks.Rmd as

---
title: "`r params$Unit`"
output: pdf_document
params:
  Unit: 68
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```

## R Markdown
Without fig.show="hold", out.width="50%" this document renders individually and as batch

```{r figures}
par(mar = c(4, 4, .1, .1))
plot(cars)
plot(mpg ~ hp, data = mtcars, pch = 19)
```

What is the issue you are getting exactly ?
When rendering rmarkdown in batch, you may want to render in background session to get a clean state at each render. Using callr package can help with that

Something like

callr::r_safe(
    function(...) rmarkdown::render(...),
    args = list(
      "Test.Rmd",
      output_file = glue::glue("REPORTS/Report Fails {set}.pdf"),
      params = list(Unit = {.x})
      envir = globalenv()
) )

or similar.

Why using {.x}here and not just .x ? Just curious

Thanks. {.x} instead of .x reflects my inexperience and lack of complete understanding of R I'm afraid. I am a 'self-taught' coder and consequently have big gaps in my understanding. Implementing callr as the code chunk below also did not work.

purrr::walk(
  .x = SurveySet,
  ~ callr::r_safe(
    function(...) rmarkdown::render(...),
    args = list(
      input = "Test.Rmd",
      output_file = glue::glue("REPORTS/Report Fails {.x}.pdf"),
      params = list(Unit = .x),
      envir = globalenv()
    ) ) )

You have been a big help however. I have discovered that the behaviour is even more odd than it first appeared . The following works.

purrr::walk(
  .x = SurveySet,
  ~ rmarkdown::render(
    input = "Test.Rmd",
    output_file = glue::glue("Report Fails {.x}.pdf"),
    params = list(Unit = .x)
  ))

ie removing the target directory. However setting the directory with the output_dir = "REPORTS" argument causes the process to fail again. But only for Test.Rmd not for TestWorks.Rmd. It is odd that this is

Error message:
output file: Test.knit.md

"C:/R/Rstudio/bin/pandoc/pandoc" +RTS -K512m -RTS Test.knit.md --to latex --from markdown+autolink_bare_uris+tex_math_single_backslash --output pandoc1cd0905719b.tex --lua-filter "C:\R\R-4.1.1\library\rmarkdown\rmarkdown\lua\pagebreak.lua" --lua-filter "C:\R\R-4.1.1\library\rmarkdown\rmarkdown\lua\latex-div.lua" --self-contained --highlight-style tango --pdf-engine pdflatex --variable graphics --variable "geometry:margin=1in"
! Undefined control sequence.
C:Users
user details....
l.77 ...ails 20_files/figure-latex/figures-side-1}

Error: LaTeX failed to compile C:/Users/../../../Survey Response/REPORTS/Report Fails 20.tex. See The R package tinytex - Helper Functions to Manage TinyTeX, and Compile LaTeX Documents - Yihui Xie | 谢益辉 for debugging tips. See Report Fails 20.log for more info.

Edit. A comment on StackOverflow also observes that replacing whitespace makes the process work ie REPORTS/Report-Fails-{.x}.pdf

Oh I did not notice whitespace. There must be something conflicting in path as we are trying our best to remove special chars and whitespace. Maybe that is causing issue :thinking:

Anwyay, it is best to not use white space and not use a dir in output_file. rmarkdown::render() works best when everything happens in the same folder. Usually if you want the outputs elsewhere, you can just copy the resulting files elsewhere after rendering and before rendering a new one.

Mixing purrr::walk() and render() and callr is not easy. Everything will have implicit environment and this may not work well.

I think you should just

  • Use a for-loop for the rendering
  • Wrap the callr call into a function and test that this function is working.

This would loook like

render_rmd <- function(...) {
   # code with callr to render a Rmd
}

for (x %in% SurveySet) {
  # render rmd for each value
}

Something like that.

Hope it helps