Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 568
AOGSTA Avatar asked Apr 06 '16 17:04

AOGSTA


2 Answers

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')
}
like image 76
AOGSTA Avatar answered Oct 03 '22 17:10

AOGSTA


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).

like image 26
Matherion Avatar answered Oct 03 '22 18:10

Matherion