Optimizing R Markdown workflow - reusing R Markdown chunks with parameters?


#1

I'm facing the following challenge: I have a long report with repeated sections (chunks) where I use the same chunk format and functions for generating plots/ tables, but they need to use a different value if 'i' (as a parameter) to select a different variable to generate all that for.

The solutions I've tried so far:

  1. ref.label= - as a chunk option where I refer a chunk before. That would generally work but as far as I know there is no possibility to somehow pass a parameter such as: i <- 2, i <- 3 in order to make the chunk render for a different variable right?

  2. child= - to reference an external Rmd file. I was thinking that I could have a universal script where the name of the file carries the parameter value, such as: Chunk_1.Rmd, and then within the file itself I have an element that tries to read the file name and subset the parameter that is then further carried across the file to generate content such as:

i <- sys.frame(1)$ofile
i <- as.numeric(str_sub(i$value, 7, 7))

I would then have another script that would populate this file as many times with a different parameter value in the title as many variables as I have for the analysis. I would like to have this workflow set up like this because whenever I need to make a change in the general format the script would just populate all the inputs automatically. However this solution doesn't seem to work for Rmd files.

So at the moment I'm stuck with this looking for a good solution. Any of you faced a similar challenge?

Thanks!


#2

I'm not sure I understood your problem, but if the only change is a different parameter, why don't you write a function in one chunk, and then you call it in each following chunk, passing a different i value as an argument? You could also put the function (and all the others used by multiple chunks) in a script functions_used_by_report.r, and then in the first chunk you source it:

```
{r setup, include=FALSE}
source("unctions_used_by_report.r")
```

#3

That's not exactly what I'm doing, let me rephrase:

  1. I have a main Rmd document and a child Rmd document

  2. The child Rmd document contains many different chunks which use a parameter to execute different functions for different variables denoted by that parameter

  3. The reason for having just one child Rmd document (instead of let's say 50 - as many as there are variables) is that whenever I want to change something in the standard layout of that child Rmd document, it would already apply for all 50 variables in the main Rmd document

  4. What I would like to have in the main Rmd document for each variable section is just something like this:

{r child='TestChunk_1.Rmd'}

which loads that child Rmd template

  1. Now, the problem is I don't how how to specify a parameter for each of this chunks in the main Rmd file so that this specific variable chunk would execute for a different variable. Example:

{r child='TestChunk_1.Rmd'}
i <- 1

{r child='TestChunk_1.Rmd'}
i <- 2

If I managed to do that that would save me tons of time whenever I would like to change something in the general format. Is that maybe a bit more clear?


#4

Hmmm. I think you did, but the problem is I don't use child documents, so I can't follow you very well. Still, could parametrized reports help in your case? Now, if you don't share a minimal reproducible example I cannot really understand what's going on (and I cannot test solutions). However, one limit of child documents is that they all share the same enviroment as the main document, unless you do something very special.
To pass parameters to child documents, all sharing a common environment:

To call multiple times the same child document, but each time with different arguments in a different environment:

Note that unfortunately the example is for .Rw (run Sweave) documents, rather than for .Rmd (R Markdown) documents, but knit_child() should work the same way for .Rmd files:


#5

I ended up finding the most obvious solution but it tremendously improved my working with large R Markdown files. My solution is the following:

{r include=FALSE}
i <- 1

{r child='My_Template.Rmd'}

{r include=FALSE}
i <- 2

{r child='My_Template.Rmd'}

  1. My_Template.Rmd - a single R Markdown template where [[i]] denotes each variable in rows, and those columns of the data frame are listed elements I would like to place on my report: ggplots, tables etc. So the entire analysis is self-contained within one, singe data frame which I mainly did with purrr

  2. In each chunk I'm importing that template and simply before it in my code I update the [[i]] value so that the subsequent row of my data frame (variable) can be selected

Hope somebody will find this useful!


#6

obvious solutions are great solutions!

you've already figured this out, but worth noting for future travelers: child documents get executed in the same environment as the parent document. I didn't realize that at first. This is handy for doing things like looping over a child document multiple times and running it with different inputs.