Elements of Solution Files

Let us dig a bit deeper into the structure of the RMarkdown file that specify an RTutor problem set. Here is the code of a simple problem set.

Important: If you want to run this example, copy the Rmd file on Github. Copy pasting the code below won’t work.

#< ignore
```{r "Create problem set files"}
ps.name = "SmallExample"; sol.file = paste0(ps.name,"_sol.Rmd")
libs = NULL # character vector of all packages you load in the problem set
create.ps(sol.file=sol.file, ps.name=ps.name, user.name=NULL,libs=libs)

## Exercise 1 -- Summary statistics

a) We often want to compute some summary statistic of a vector.
For example:
#< task
x = 10:20
# Computing the sum of x
Now compute the mean of x.

As in a normal RMarkdown down file we have text and code chunks intermingled. In addition RTutor recognizes several keywords with special meaning.

In the example above, we have:

  • An exercise header starting with ## Exercise.
  • There is an ignore block starting with the line #< ignore and ending with the line #>. Inside the ignore block we have the setup chunk.
  • Inside the first real chunk we have a task block starting with the line #< task and ending with the line #> Chunk code inside a task block will be shown to students. Chunk code outside any block describes the sample solution that will not be shown.

Run the setup chunk and take a look at the empty problem set SmallExample.Rmd that you can give to students. Places where students have to enter code will be marked by.

```{r }
# enter your code here ...

Below we give an overview of the most important special keywords and blocks you can use to specify an RTutor problem set.

Exercise header

A solution file must consist of one or more exercises. An exercise starts with a line like

## Exercise 1 -- Summary statistics

You can pick any label for the exercise (it can include spaces). Yet, the recommend format for the exercise name is an exercise number, optionally followed by -- and a short description, as in the example above.

It is necessary that your line starts with

## Exercise 

parts a), b) …

RTutor recognizes lines in the exercise description that start with a) or ii) etc. as a “part” of an exercise and will use this information when automatically naming the code chunks in the empty problem set.

Task blocks and variants

By default if you write code in a chunk of your solution file, it means that this is the sample solution that the user should replicate. This will not be shown to the user. However, often we want to show some code to the user. For this task blocks and its variants are useful.

task blocks

Code inside a task block will be shown to the user. Here is an example:

#< task
x = 10:20
# Compute the mean of x

The definition of x and the R comment describing is in the the task block and will be shown to the user. Yet the last line is outside the task block and will not be shown, but shall be entered by the user herself.

task_notest vs task blocks

Code in a normal task block will still be checked by RTutor. This means if a user modifies the given code in a task block, RTutor will not accept the solution. This requirement is useful if the task block specifies variables that will be used in later computations.

Other times, we just want to show some output and no harm is done if the user changes the code. You should then put such code in a task_notest block. Here is an example:

#< task_notest
# Here is a plot
plot(x=1:10,y= (1:10)^2)

Code in a task_notest block will never be checked and created variables will not be available in later blocks. This makes it also faster to evaluate task_notest blocks than task blocks.

fill_in blocks

Sometimes, we would like students to fill in code at some place holders. For example, instead of writing a long line of ggplot commands, we want the user to just fill in the relevant aesthetics:

ggplot(data, aes(x= ___, y = ___)) +
  geom_point() +
  ggtitle("My first ggplot!")

You specification in your solution file would look like

#< hint
cat("Just fill in the right values for x and y in the placeholders below.")
#< fill_in
ggplot(data, aes(x= ___, y = ___)) +
  geom_point() +
  ggtitle("My first ggplot!")
# Below the fill_in block put the sample solution
ggplot(data, aes(x=weight, y = height)) +
  geom_point() +
  ggtitle("My first ggplot!")

Please use three underscores ___ as placeholders or change the argument placeholder in create.ps if you want another placeholder string for your problem set. The problem is that most nice placeholder strings create syntactically incorrect R code, which would mess up hints. The default placeholder ___ will be internally converted to a variable name to allow parsing a student’s expression that still contains placeholders.

You should try to set your placeholders such that you get a syntactically R expression if the placeholder were a valid R variable name. If that is not possible, you should add a # in front of every line of your fill_in block so that create.ps can correctly parse your expression. Here is an example:

#< fill_in
# # Insert for ___ the correct operator to multiply x with y
# x ___ y

The initial # will be removed when shown to the student.

notest blocks

Code in a notest block will neither be shown to the user nor is the user required to replicate it. It will be just shown for information in the created _sample_solution.Rmd and _output_solution.Rmd files.

You may not very often use notest blocks. But one use case is the following. You may have a difficult quiz in a shiny based problem set that can be easier solved if the user can freely experiment with some code in the chunk above. This means the user is free to enter, what she likes in the chunk. Yet, you still put some code that would solve the quiz in the notest block if you later want to distribute sample solutions.

Blocks for customized hints and tests

There are several block types that are related to customized hints and tests:

hint, add_to_hint, compute, test, and test_arg. See the section on customized hints and tests for details.

Block types used outside of chunks

The blocks described above all started and ended within a chunk. However, RTutor also recognizes some block types that start and end outside of chunks and may contain one or several chunks.

ignore blocks

All code in ignore blocks will not be part of the problem set. For example, the setup chunk that contains the code to compile the problem set will be put in an ignore block.

Unfortunately, ignore blocks cannot nest other blocks starting with #<.

quiz blocks

For problem sets designed for the web browser, you can easily specify quizzes. Just take a look at the example problem on RTutor’s Github page here.

Note that you have to add the argument addons="quiz" to your call to create.ps in your setup chunk.

info blocks

Info blocks are declared outside of code chunks and start with #< info and end with #>. In the shiny version of the problem set the content of an info block is shown inside a collapsible note. In the RStudio version, info blocks are less useful.

Info blocks are helpful to keep the main problem set text brief enough, while at the same time allow a wide range of detailed background information. Here is an example:

  #< info "useful functions for numeric vectors"
    Here are examples for useful R functions
    max(c(1,5,2)) # returns maximum
    min(c(1,5,2)) # returns minimum
    sum(c(1,5,2,NA), na.rm=TRUE) # returns sum of all numbers, ignore NA
    cumsum(c(1,5,2)) # returns cummulated sum
    diff(c(1,5,2)) # returns the vector of differences

An info block can contain normal text and also code chunks. When the problem set is created all info blocks will be compiled via the knitr and markdown packages to html text. Since info blocks will be complied already when the problem set is created, you cannot used any variables that are declared outside the info block in the info block code chunks.

If you want info blocks with code chunks that the user can solve use a note block.

Notes – Or info blocks that can contain chunks

Info blocks cannot include chunks that the user shall solve. Notes are a variant of info blocks that can contain chunks for the user to be solved.

The syntax for note blocks is non-standard, since I never updated RTutor to a parser that generally handles nested #<#> blocks. Here is an example:

#! start_note "A note with a chunk"
This is a note.

```{r "1_1  6",optional=TRUE}
#< task
# show that all integers between 0 and 10
#! end_note 

Everything between the lines

#! start_note "Title"


#! end_note

will be shown in a note. Chunks inside the note can be solved by users. They should have optional=TRUE in the chunk header.

preknit blocks (just knit as RMarkdown)

preknit blocks are declared outside of code chunks and start with #< preknit and end with #>.

Any rmd code inside a preknit block will be knitted at compile-time and shown as usual RMarkdown output in the shiny based version of the problem set. This is very similar to the output of an info block, except that it is not put into a collapsible.

Note that code that was evaluated in an earlier preknit block or earlier info block will be available at compile time at later info or preknit blocks, no matter which exercise the blocks are in. If you want just to do some preliminary computations for later info or preknit blocks without showing any output, add a chunk with the chunk option include=FALSE in a preknit block.

award blocks

Isn’t it amazing when video game players play for hours and hours, doing sometimes quite repetitive and boring tasks, just in order to earn some virtual points or virtual trophies? Well it seems that many people can be motivated, at least to some degree, by such stuff (see Wikipedia).

Since a main motivation for RTutor is to make learning R, as well as statistical and economic concepts, more interesting and more entertaining, it seems natural to borrow some ideas from computer games.

You can give students awards if they have solved a problem by adding an award block, like e.g.

  #< award "mean means mean"
  Well, in some occasions one can just guess the name of an R function.
  The function to compute the mean of a vector or matrix
  is called 'mean'.
  Usually, it is much quicker to goggle than 
  to guess function names, however.

Just write some markdown text inside the block. You can also include HTML tags, and e.g. embed a youtube video.

The student sees the award once the chunk efore the award is solved. By typing awards() in the R console all awards are shown.

Note that even the world’s probably biggest data collecting organisation has used awards to teach it analysists…


Special chunks options

Optional chunks

By default you have to solve all chunks in an exercise in the given order. If you set the chunk option optional=TRUE, a chunk need not be solved in order to continue. Example:

```{r "1_b", optional = TRUE}
# Code here


This is in particular useful if you use notes that contain chunks. Note that variables that have been computed in optional chunks will not be known in later chunks.

Note that optional is not a chunk option known by knitr but only used for RTutor.

Chunks with HTML output

You can specify chunks whose output is native HTML code, e.g. if you want to show an HTML table or show a motion plot. As in normal rmarkdown, you can do so by setting the chunk option results= "asis". Here is an example from an interactive problem set that shows a motion plot:

```{r "2_1_a_example", results = 'asis'}
#< task
mp = gvisMotionChart(Int.data,
       idvar = "country", timevar = "year")
plot(mp, tag = "chart")

There are a lot of R packages that help creating nice HTML tables, like stargazer, or hwriter.

Chunks with HTML Widgets as outputs

It is also possible to have chunks that have HTML widgets as output. If you use the shiny based version of RTutor you then need some additional chunk options. Here is an example for the leaflet widget:

```{r output="htmlwidget", widget="leaflet"}
#< task_notest
SFmap <- leaflet() %>% 
  addTiles() %>% 
  setView(9.9620289,48.4251394, zoom = 11) %>% 
    popup = 'RTutor was created here at Ulm University')

The widget argument is typically the name of the R package in which the html widget is specified.

Customizing data frame printer

In the shiny version of RTutor data frames are by default shown as HTML tables. You can set global options or chunk options that customize its appearance.

For details, take a look at this example.

Specifying figure width and height and other knitr chunk options

If your chunk plots a figure, you may want to specify the width and height of the resulting figure. You can do this like for normal RMarkdown files with the chunk options fig.width and fig.height that specify width and height in inches.

```{r "1_a", fig.width=12, fig.height=5}
#< task

You can also specify other chunk options of the knitr package. An overview is given here: