3

I have been running some small R tutorials / workshops for which I keep my 'challenge scripts' in Rmarkdown documents. These contain free text and R-code blocks. Some of the code blocks are prefilled (eg, to set up datasets for later use), whereas some are there for the attendees to fill-in code during the workshop.

For each challenge script, I have a solution script. The latter contains all the free text of the former, but any challenge-blocks have been filled in (there's an example of a solutions workbook here).

I don't really want to keep two closely related copies of the same file (the challenge and the solutions workbook). So I was wondering if there's an easy way to construct my challenge scripts from my solutions scripts (or the solutions script from a challenge-script and an R-script containing just the solution blocks).

For example, is there an easy way to replace all named code-blocks in one Rmarkdown file with the correspondingly-named code block from another rmarkdown file?

That is, if I have

challenge.Rmd

HEADER

INTRODUCTION

Today we're going to learn about sampling pseudo-random numbers in R

```{r challenge_1}
# Challenge 1: Make a histogram of 100 randomly-sampled 
# normally-distributed values
```

BLAH BLAH

END_OF_FILE

solutions.Rmd

HEADER

```{r challenge_1}
# Challenge 1: Make a histogram of 100 randomly-sampled 
# normally-distributed values
hist(rnorm(100))
```

END_OF_FILE

How do I replace challenge_1 from challenge.Rmd with challenge_1 from solutions.Rmd?

All the best

Russ Hyde
  • 2,154
  • 12
  • 21
  • Just to be clear, you want to give the challenge script to the participants of the tutorial, or do you just give the html-files? – kath Apr 19 '18 at 08:23
  • I give the .Rmd of the challenges to the participants. – Russ Hyde Apr 19 '18 at 08:25
  • One way to do this (also not really pretty): For each challenge in your challenge document create a .Rmd for the solution and then use it as a child in your original document. Then add a parameter to the chunks (something like `eval = show_solution`) which is set to FALSE for the students. As they don't have the solution .Rmd they cannot see them.... – kath Apr 19 '18 at 08:29

1 Answers1

2

This is one approach:

challenge.Rmd

---
output: html_document
---

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

```{r child="solution.Rmd", eval=show_solution}
```

Today we're going to learn about sampling pseudo-random numbers in R

```{r challenge_1}
# Challenge 1: Make a histogram of 100 randomly-sampled 
# normally-distributed values
```

```{r challenge_1_s, eval=show_solution, echo=show_solution}
```


```{r challenge_2}
# Challenge 2: Make a histogram of 100 randomly-sampled 
# uniform-distributed values
```

```{r challenge_2_s, eval=show_solution, echo=show_solution}
```

solution.Rmd

```{r challenge_1_s, eval=FALSE, echo=FALSE}
# Challenge 1: Make a histogram of 100 randomly-sampled 
# normally-distributed values
hist(rnorm(100))
```

```{r challenge_2_s, eval=FALSE, echo=FALSE}
# Challenge 2: Make a histogram of 100 randomly-sampled 
# uniform-distributed values
hist(runif(100))
```

With the show_solution parameter you can include or exclude the solution from you rmarkdown. The participants are not able to compile the document for show_solution = TRUE unless they have the solution.Rmd. For show_solution = FALSE there's no problem and it compiles nicely.

kath
  • 7,624
  • 17
  • 32
  • what I love is that the solution-blocks can refer to variables that are defined in the challenge-blocks, despite being in two different rmarkdown scripts. I've obviously not looked into the inner workings of rmarkdown/knitr and child-documents before. Thanks again – Russ Hyde Apr 19 '18 at 11:51