AOGSTA
AOGSTA

Reputation: 708

Knitr: one plot per .tabset in for-loop

Long story short, I'm trying to use knitr to dynamically create separate tabsets and render a plot within each tabset. Below is a description of my failed attempts. I would appreciate a solution, but I suspect I'm just not understanding the fundamental way in which knitr renders output. So if you could point me to resources or provide some conceptual guidance, that would also be appreciated.

Dynamically creating the tabsets themselves is easy. Here is my .R file

#' ---
#' title: 
#' author: 
#' date: 
#' output:
#'    html_document
#' ---

#' # {.tabset}
#+ results='asis', echo=FALSE
for(i in 1:10){
  cat('##',i,' \n')
}

When I call rmarkdown::render() on this .R file, I get 10 empty tabsets (see below). I'm not really sure what cat does or why the \n is necessary (this is where some conceptual explanation would be appreciated), but it works. enter image description here Now I add in a boxplot() call to the for-loop and expect to get the same boxplot on each tabset.

#' ---
#' title: 
#' author: 
#' date: 
#' output:
#'    html_document
#' ---

#' # {.tabset}
#+ results='asis', echo=FALSE
for(i in 1:10){
  cat('##',i,' \n')
  boxplot(iris$Sepal.Length~iris$Species)
}

But instead, the first tab comes up empty and the second tab is this vomit of output. enter image description here

If I add another cat() with two "\n" characters, then all the tabs appear, but only the second tab is populated with the chart. The other tabs are empty.

#' ---
#' title: 
#' author: 
#' date: 
#' output:
#'    html_document
#' ---

#' # {.tabset}
#+ results='asis', echo=FALSE
for(i in 1:10){
  cat('##',i,' \n')
  boxplot(iris$Sepal.Length~iris$Species)
  cat(' \n \n')
}

enter image description here

Upvotes: 8

Views: 4699

Answers (2)

Matherion
Matherion

Reputation: 667

I'm not sure, but based on these patterns, I'd say that boxplot, like most of R's native plotting functions, 'overplot' each other. So, rmarkdown::render just sees one figure being generated. By calling plot.new you're telling R to 'finalize' the current plot and then start writing plot output to a new plot. This results in ten different plots.

A tip that I find useful and you might find useful as well: when debugging/troubleshooting/figuring out the dynamics of rmarkdown::render and R Markdown, it can help to also inspect the 'raw' Markdown output. You can tell rmarkdown::render to keep this file around by including keep_md: TRUE in the YAML header (see the **Advance http://rmarkdown.rstudio.com/html_document_format.html for examples and more information).

Upvotes: 2

AOGSTA
AOGSTA

Reputation: 708

So I found a solution, but still do not know why it works. Would appreciate any feedback. Adding plot.new() before each plot() works.

#' ---
#' title:
#' author: 
#' date: 
#' output:
#'    html_document
#' ---

#' # {.tabset}
#+ results='asis', echo=FALSE
for(i in 1:10){
  cat('##',i,' \n')
  plot.new()
  boxplot(iris$Sepal.Length~iris$Species)
  cat(' \n \n')
}

Upvotes: 6

Related Questions