What is the problem?

In RMarkdown, sometimes, I want to display a full code chunk, uninterrupted, and have it followed by one or more figures generated in the same code chunk, but while also ignoring any text output.

By default, RMarkdown will interrupt a single code chunk to display text and figure output from executable statements. Sometimes, this behavior is desired. However, for tutorials on blogs, this behavior can be annoying to users, especially when a code chunk spans multiple statements that generate output. When a code chunk contains more than a few statements that generate output, a user wishing to implement the code will have to scan through the full post collecting all of the individual statements and editing out undesired content.

The default settings for the knitr package ease the burden somewhat by getting rid of > characters and prepending text output with a # character. Even so, without editing, at best, a simple copy-paste operation will still keep a lot of unnecessary code lines, and at worst, the script will not run without heavy editing.

What are potential solutions?

Solution 1 - Write very short code chunks

Pro: The solution is easy to implement.

Con: The solution doesn’t work if you want to use longer code chunks, which is the most common use case.


Solution 2 - Use knitr features with code chunks

Pro: Tremendous Flexiblity

Con: Really, none.

If you decide to have the code chunk located in an external file, which is my preference, then you have to make sure that the parent RMarkdown file has access to the externally located script. Alternatively, you can locate the code itself in the RMarkdown file itself. For this example, the code will be located in an external script file.

How is this solution implemented?
  1. Create an external R-script (i.e. a standard ‘*.R’ file) as you normally would, but with one key difference: use a special knitr-aware comment syntax to name each code chunk to be executed by knitr in a separate document. Athough this syntax is used in the examples in this post, for more details, see Zev Ross’ blog post or read the knitr documentation on code chunks (links to both are included below).

  2. In your RMarkdown setup block, read the external code chunks with a call to knitr::read_chunk()

  3. Call your code chunks twice in your RMarkdown document.

The first time, you call the code chunk solely to display the source code. Then, you call it again. However, this time, you execute the code, but suppress all text output only by setting a knitr code chunk option, results = 'hide'. This option suppresses all normal text output, but figures will still be plotted. If desired, you can also suppress warning and messages, too, by setting the appropriate chunk options. See the knitr documentation on chunk options for more information.

Although this approach is a little more work than a simple, basic RMarkdown workflow, it has the advantage of being very robust. When a code chunk changes, simply run knitr again to generate the resulting RMarkdown and it will always be correct.

This full process is illustrated below (see Examples), but if you want to read more about creating external code chunks and calling them in an RMarkdown file, check out this great blog post by Zev Ross. Furthermore, reviewing the full list of knitr chunk options is helpful, too.


Examples

Demonstrating the Problem


Example 1 - The Full Code Chunk Unevaluated

Here’s the full code chunk that I want to call.

  # Set up some sample data
  xvars <- -10:10
  yvars <- xvars^2

  # Show the xvars
  xvars

  # Create a plot
  plot(xvars, yvars,
       main = "Sample Plot",
       xlab = "x",
       ylab = expression(x^2),
       type = "l",
       lwd = 2,
       col = "blue")
  points(xvars, yvars, pch = 16, col = "red", cex = 1.5)


  # Display the date and time
  Sys.Date()

Example 2 - The Full Code Chunk Evaluated

Next, I reference the same code chunk as above, but this time, I am also evaluating the code.

  # Set up some sample data
  xvars <- -10:10
  yvars <- xvars^2

  # Show the xvars
  xvars
##  [1] -10  -9  -8  -7  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5   6
## [18]   7   8   9  10
  # Create a plot
  plot(xvars, yvars,
       main = "Sample Plot",
       xlab = "x",
       ylab = expression(x^2),
       type = "l",
       lwd = 2,
       col = "blue")
  points(xvars, yvars, pch = 16, col = "red", cex = 1.5)

  # Display the date and time
  Sys.Date()
## [1] "2018-12-13"

Do you notice how the prior code chunk gets interrupted by its own output when it is executed? This behavior was not what I desired. Rather, I simply wanted the full code chunk to be printed followed by the resulting figure plot.


Example 3 - Evaluating the Full Code Chunk, but with the results = 'hide' option

In this example, I set knitr::opts_chunk$set(results = 'hide'), which suppresses all text output.

  # Set up some sample data
  xvars <- -10:10
  yvars <- xvars^2

  # Show the xvars
  xvars

  # Create a plot
  plot(xvars, yvars,
       main = "Sample Plot",
       xlab = "x",
       ylab = expression(x^2),
       type = "l",
       lwd = 2,
       col = "blue")
  points(xvars, yvars, pch = 16, col = "red", cex = 1.5)

  # Display the date and time
  Sys.Date()

Although this result is closer to what I wanted, it’s still not right. This example is somewhat better because the text output is fully suppressed, and the figure is still plotted. However, it’s still not exactly what I wanted because the figure plot interrupts the code chunk. Remember, I wanted all figures to be plotted after the code chunk.


The Full Solution

  1. First, create one RMarkdown file and one R-script file, both in the same directory location.

  2. Name the R-Script file MyExternalRCode.R and insert the code shown below into it.

    # Create a label for the knitr code chunk name 
    ## @knitr ExternalCodeChunk020 
    
      # Set up some sample data 
      xvars <- -10:10 
      yvars <- xvars^2 
    
      # Display the xvars 
      # Note that I don't really want to display the xvars, but this line is included 
      # to demonstrate that text output won't show up in the RMarkdown in this example. 
      xvars 
    
      # Create the plot 
      plot(xvars, yvars, 
           main = "Sample Plot", 
           xlab = "x", 
           ylab = expression(x^2), 
           type = "l", 
           lwd = 2, 
           col = "blue") 
      points(xvars, yvars, pch = 16, col = "red", cex = 1.5) 
    
      # Display the date and time 
      # Similar to xvars above, this line is intended to demonstrate that text output 
      # won't be displayed in this RMarkdown example. 
      Sys.Date() 
    
  3. Insert the following code into the R Markdown File

    --- 
    title: "Example of Using Externally Located Code Chunks" 
    author: "Firstname Lastname" 
    date: "December 13, 2018" 
    output: html_document 
    --- 
    
    ```{r setup, include=FALSE} 
      knitr::opts_chunk$set(echo = TRUE) 
      knitr::read_chunk("MyExternalRCode.R") 
    ``` 
    
    This first code chunk prints the externally located code, 
    but it does not execute the code. The next code chunk 
    executes the externally located code, but it does not print code 
    itself. Text output is suppressed, and figures are plotted, 
    but only after all of the code is executed. 
    
    ```{r DisplayCodeChunk, eval = FALSE, echo = TRUE} 
      <<ExternalCodeChunk020>> 
    ``` 
    
    
    ```{r RunCodeChunk, echo = FALSE, eval = TRUE, results = 'hide'} 
      <<ExternalCodeChunk020>> 
    ``` 
  4. knit the code as you normally would.


Example Output

This first code chunk prints the externally located code, but it does not execute the code. The next code chunk executes the externally located code, but it does not print code itself. Text output is suppressed, and figures are plotted, but only after all of the code is executed.

    # Set up some sample data
    xvars <- -10:10
    yvars <- xvars^2
  
    # Display the xvars
    # Note that I don't really want to display the xvars, but this line is included
    # to demonstrate that text output won't show up in the RMarkdown in this example.
    xvars
  
    # Create the plot
    plot(xvars, yvars,
         main = "Sample Plot",
         xlab = "x",
         ylab = expression(x^2),
         type = "l",
         lwd = 2,
         col = "blue")
    points(xvars, yvars, pch = 16, col = "red", cex = 1.5)
  
    # Display the date and time
    # Similar to xvars above, this line is intended to demonstrate that text output
    # won't be displayed in this RMarkdown example.
    Sys.Date()