Can one choose multiple values for a param in YAML for parameterized markdown?

rmarkdown
rstudio
#1

The YAML header allows us to set parameters using the params and choices variables. However, it seems that we can only choose one value from the choices list. Is there a way to select multiple (and hence to have a multi-item vector parameter)? For example, in each analysis report, I would like to compare two fruits (apple vs orange, apple vs pear, etc).

Since I don't know of a way to multi-select from choices, I tried:

params:
  fruits:
    value: !r c("apple","orange")
    choices:
      - !r c("apple","orange")
      - !r c("apple","pear")
      - !r c("pear","orange")

But I got this error " The following parameters cannot be customized: fruits". So I don't even get the choices list to choose from. But it actually works for the default value if I ignore the error and click "Knit".

0 Likes

#2

I haven't used the choices option, but couldn't you pass a vector of two values as a single parameter? For example, to knit an rmarkdown file for every pair of fruits you could do:

library(rmarkdown)
library(tidyverse)

x = c("apple", "pear", "orange", "cherry")

map(combn(x, 2, simplify=FALSE),
    ~ render(input="myfile.rmd", 
             output_file = paste("myfile", .x, ".pdf"),
             params=list(fruits=.x)))

Then, in myfile.rmd you would presumably have code that would compare each pair of fruits that was passed in as params$fruits.

0 Likes

#3

Thanks @joels! This will not output the user interface to choose, but most of the time I run all combinations anyway. So this will be very helpful. I tried it out, but got a "Error: pandoc document conversion failed with error 1". It's a separate question (perhaps some pandoc setting?), but thought you maybe able to point out the issue. Here is the output when running the knit:

R-3.5.1> map(combn(x, 2, simplify=FALSE),
+     ~ render(input="<full_path>/test_markdown3.Rmd", 
+              output_file = paste("test", .x, ".html"),
+              params=list(fruits=.x)))


processing file: test_markdown3.Rmd
  |.............                                                    |  20%
   inline R code fragments

  |..........................                                       |  40%
label: setup (with options) 
List of 5
 $ include: symbol F
 $ echo   : logi FALSE
 $ results: chr "hide"
 $ message: logi FALSE
 $ warning: logi FALSE

  |.......................................                          |  60%
  ordinary text without R code

  |....................................................             |  80%
label: unnamed-chunk-1
  |.................................................................| 100%
  ordinary text without R code


output file: test_markdown3.knit.md

/<some_path>/apps/pandoc/1.19.2.1-goolf-1.7.20/bin/pandoc +RTS -K512m -RTS test_markdown3.utf8.md --to html4 --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output pandoc2f01f5c4dacfa.html pandoc2f01f29532b9d.html --smart --email-obfuscation none --self-contained --standalone --section-divs --template /<some_path>/apps/R/3.5.1-goolf-1.7.20/lib64/R/library/rmarkdown/rmd/h/default.html --no-highlight --variable highlightjs=1 --variable 'theme:bootstrap' --include-in-header /tmp/RtmpCNYbIW/rmarkdown-str2f01f2ce20a4c.html --mathjax --variable 'mathjax-url:https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML' --variable code_folding=hide --variable code_menu=1 
pandoc: pandoc2f01f29532b9d.html: openFile: does not exist (No such file or directory)
Error: pandoc document conversion failed with error 1
In addition: Warning message:
In if (nzchar(file_ext)) paste(".", file_ext, sep = "") else "" :
  the condition has length > 1 and only the first element will be used

Note that I do need to put in the full path of the rmarkdown file even though they are in the same path. Not sure why. Also, what does the "." in ".x" mean?
Thanks!

0 Likes

#4

I'm not sure what specifically is going wrong. Could you post a self-contained reproducible example (i.e., a minimal rmarkdown document and perhaps a small data sample, if necessary (though you could probably build the data sample into the rmarkdown document), that I can run on my machine and that reproduces the error you're getting?

The .x is a "pronoun" that refers back to the first argument of map (combn(x, 2, simplify=FALSE), which is the list we're iterating over. Each .x is one of the elements of combn(x, 2, simplify=FALSE)). Also, in case it was confusing, the x and the .x have nothing to do with each other. I should have called the x vector fruits or something like that to avoid confusion. See the help for map for more details on the .x argument.

0 Likes

#5

Thanks @joels for the explanation. Here is the minimal Rmd:

---
title: "Compare `r params$compareFruits`"
params:
  compareFruits: !r c("apple","orange")
output:
  html_document:
    code_folding: hide
---

```{r}
cat("calling params$compareFruits: \n", params$compareFruits)
```

And the R script to knit the Rmd:

library(rmarkdown)
fruits = c("apple", "pear", "orange")

map(combn(fruits, 2, simplify=FALSE),
    ~ render(input="~/test_markdown3.Rmd", 
             output_file = paste("test", .x, ".html"),
             params=list(compareFruits=.x)))

And some of the sessionInfo (the full sessionInfo maybe too long for here):

rmarkdown_1.10
knitr_1.20
pandoc/1.19.2.1-goolf-1.7.20
0 Likes

#6

It seems the problem is in the file name, since combn returns a list for each combination which causes paste to vectorize over it.

For example, the first element in the list created by combn is [1] "apple" "pear" so paste will create this:

paste("test", combn(fruits, 2, simplify=FALSE)[[1]], ".html")
[1] "test apple .html" "test pear .html"

You can collapse the elements into each other and create the filenames that way, which you can see below:

library(rmarkdown)

fruits = c("apple", "pear", "orange")

purrr::map(combn(fruits, 2, simplify=FALSE),
    ~ render(input="params.Rmd", 
             output_file = paste0( paste0(.x, collapse = "_"), ".html"), # File name as fruit combination
             params=list(compareFruits=.x)))
1 Like

#7

Ah, yes! Thanks @jdb ! It works now.

0 Likes

#8

I forgot to account for the two-element vector represented by .x, treating it as if it were a single element. Thank you @jdb for the correction!

0 Likes