Using layout with knitr - r

I want to make a single figure in R with two plots in a markdown file with knitr. Normally, this is easy to do with layout(t(1:2)) or par(mfrow=c(1,2)). Can I do this with knitr, or will it always make two separate figures?
Here is a minimum working example which creates a file called ./junk.Rmd and ./junk.md in your working directory along with two files ./figure/junkislands1.png (which only includes the first plot) and ./figure/junkislands2.png (which includes both plots that I want).
require(knitr)
temp <- "```{r junkislands, fig.width=8, fig.height=5}
layout(t(1:2))
pie(islands)
barplot(islands)
```"
cat(temp, file="junk.Rmd")
knit("junk.Rmd", "junk.md")
The problem isn't so much that it creates two .png files, but rather that the markdown file junk.md includes both of them.
When I make that markdown into html, it includes both .png files when I only want the one with both figures plotted.
Here is the file junk.md that is generated from knitr:
```r
par(mfrow = c(1, 2))
pie(islands)
```
![plot of chunk junkislands](figure/junkislands1.png)
```r
barplot(islands)
```
![plot of chunk junkislands](figure/junkislands2.png)

Have a look at http://yihui.name/knitr/options and specifically fig.keep. I think you want fig.keep = 'last'
require(knitr)
temp <- "```{r junkislands, fig.width=8, fig.height=5, fig.keep = 'last'}
layout(t(1:2))
pie(islands)
barplot(islands)
```"
cat(temp, file="junk.Rmd")
knit("junk.Rmd", "junk.md")
gives
```r
layout(t(1:2))
pie(islands)
barplot(islands)
```
![plot of chunk junkislands](figure/junkislands.png)

Related

Dynamic plots and tables inside Rmarkdown

I am new to Rmarkdown and shiny and forgive me for some naive questions. I have build a code in two parts first where I do all the processing and second where I call the Rmarkdown to knit it.
The first code example.R is as follows and works fine independently (with only glitch of plots being trimmed from sides):
# Create a label for the knitr code chunk name
## #knitr ExternalCodeChunk020
library(Seurat)
library(tidyverse)
library(sleepwalk)
library(gridExtra)
library(plotly)
library(DT)
# Set up some sample data
data(mtcars)
# 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.
a <- ggplotly(ggplot(mtcars, aes(cyl,mpg)) + geom_boxplot())
b <- ggplotly(ggplot(mtcars, aes(wt,mpg)) + geom_point())
subplot(a, b, nrows=1)
DT::datatable(mtcars, class = "cell-border stripe", rownames = FALSE, filter ="top",
editable =TRUE, extension = "Buttons", options = list(dom="Bfrtip",
buttons =c("copy", "csv", "excel", "pdf","print")))
ggplotly(ggplot(mtcars,aes(x=mpg)) + geom_histogram(binwidth=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()
The second part of the code (mrkdwn.Rmd) is where I try to knit and generate Rmarkdown report:
---
title: "Code Chunks"
author: "Author"
date: "November 13, 2020"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
knitr::read_chunk("example.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 = FALSE}
<<ExternalCodeChunk020>>
```
```{r RunCodeChunk, echo = FALSE, eval = TRUE, results = 'hide'}
<<ExternalCodeChunk020>>
```
the output doesn't contain plots. I am not sure what is going wrong, could anyone of you help me in fixing this.
I know that an easy fix is to put both parts of the code together inside the Rmarkdown like this:
---
title: "test3"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r}
library(Seurat)
library(tidyverse)
library(sleepwalk)
library(gridExtra)
library(plotly)
library(DT)
# Set up some sample data
data(mtcars)
# 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.
a <- ggplotly(ggplot(mtcars, aes(cyl,mpg)) + geom_boxplot())
b <- ggplotly(ggplot(mtcars, aes(wt,mpg)) + geom_point())
subplot(a, b, nrows=1)
DT::datatable(mtcars, class = "cell-border stripe", rownames = FALSE, filter ="top",
editable =TRUE, extension = "Buttons", options = list(dom="Bfrtip",
buttons =c("copy", "csv", "excel", "pdf","print")))
ggplotly(ggplot(mtcars,aes(x=mpg)) + geom_histogram(binwidth=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()
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Since I need to process large datasets and generate graphs/plots and table I would prefer to keep them separately, so that my Rmarkdown doesn't crash. May be this is wrong and there could be a better approach, please suggest.
Many thanks for your time and help.

I have a for loop of qplots, how can you structure the plots individually using LaTeX code e.g adding captions to the plots

\begin{figure}[h]
\centering
<<echo=FALSE>>=
for(i in 2:38){
print(my_plot_function(i))
}
#
\end{figure}
This is my code, but what is happening is that when I compile my PDF I only get the first two plots that fit on the first page and I do not get the rest of the plots.
I would like to have all of the plots on separate pages.
And how would I go about adding captions to each individual plot in the for loop.
\documentclass{article}
\begin{document}
<<echo = FALSE, fig.cap = c("First, Second, Third"), results = "asis">>=
library(ggplot2)
for (i in 1:3) {
print(qplot(x = 1, y = i))
cat("Arbitrary \\LaTeX code! \\clearpage")
}
#
\end{document}
You can use the chunk option fig.cap to add captions to your plots. Note that this will wrap your figure in a figure environment, turning it into a float.
Use the chunk option results="asis" to be able to print arbitrary text (including LaTeX markup) into your document using cat().

Remove progress bar from knitr output

I'm analyzing some data and would like to do a Simpsons paradox on R. I've installed the Simpsons package and loaded the library. Here is an example based on the package documentation:
---
output: html_document
---
```{r}
library(Simpsons)
#generating data
Coffee1=rnorm(100,100,15)
Neuroticism1=(Coffee1*.8)+rnorm(100,15,8)
g1=cbind(Coffee1, Neuroticism1)
Coffee2=rnorm(100,170,15)
Neuroticism2=(300-(Coffee2*.8)+rnorm(100,15,8))
g2=cbind(Coffee2, Neuroticism2)
Coffee3=rnorm(100,140,15)
Neuroticism3=(200-(Coffee3*.8)+rnorm(100,15,8))
g3=cbind(Coffee3, Neuroticism3)
data2=data.frame(rbind(g1,g2,g3))
colnames(data2) <- c("Coffee","Neuroticism")
example <- Simpsons(Coffee,Neuroticism,data=data2)
plot(example)
```
This is returning a plot with 3 clusters (exactly what I need). However, when I Knit the Rmd file to HTML, I'm getting a lot of equals signs (======) with a percentage next to it like a loading grid which I would like to remove from my final output.
You can suppress any output messages in R by setting the knitr chunk option. If we wish to hide all code output other than plots, we can use the following solution:
---
output: html_document
---
```{r echo=FALSE, results='hide', fig.keep='all', message = FALSE}
library(Simpsons)
#generating data
Coffee1=rnorm(100,100,15)
Neuroticism1=(Coffee1*.8)+rnorm(100,15,8)
g1=cbind(Coffee1, Neuroticism1)
Coffee2=rnorm(100,170,15)
Neuroticism2=(300-(Coffee2*.8)+rnorm(100,15,8))
g2=cbind(Coffee2, Neuroticism2)
Coffee3=rnorm(100,140,15)
Neuroticism3=(200-(Coffee3*.8)+rnorm(100,15,8))
g3=cbind(Coffee3, Neuroticism3)
data2=data.frame(rbind(g1,g2,g3))
colnames(data2) <- c("Coffee","Neuroticism")
example <- Simpsons(Coffee,Neuroticism,data=data2)
plot(example)
```
I would note that this package seems to print out a lot more content that most packages, and therefore the combination of options are quite long.
An easier method would probably be to move the plot to a separate chunk and have all the analysis run before it. The include argument can be used to suppress all outputs, but this includes plots, hence why we must use two chunks:
```{r, include = FALSE}
# your code to build model
```
```{r}
plot(example)
```
Check out the full list of knitr chunk options here

Rstudio does not make plots with knit Word

I seem to have discovered an odd behaviour with the knit Word command in RStudio
This works:
```{r qplot, fig.width = 6, fig.height=6, message=FALSE}
library(ggplot2)
summary(cars)
qplot(speed, dist, data = cars) + geom_smooth()
````
this does not work
```{r q plot, fig.width = 6, fig.height=6, message=FALSE}
library(ggplot2)
summary(cars)
qplot(speed, dist, data = cars) + geom_smooth()
```
returning this message:
pandoc.exe: Could not find image `./test_files/figure-docx/q%20plot.png', skipping...
The issue seems to be with the name of the chunk (i.e. qplot vs. q plot). When there is a space in the chunk name the plot does not render.
It only seems to affect the rendering of Word documents. Rendering html works fine.
I'm using RStudio 0.98.1028 and R3.1.1 on windows 7.
Has anyone else encountered this behaviour?
update
a space after the chunk name also seems to elicit the same behaviour:
this does not work
```{r q_plot , fig.width = 6, fig.height=6, message=FALSE}
library(ggplot2)
summary(cars)
qplot(speed, dist, data = cars) + geom_smooth()
```
Posting the solution in case someone runs across this in future.
From Ben Bolker in the comments Avoid spaces and periods . in chunk labels and directory names as stated in the knitr documentation http://yihui.name/knitr/options.
This error only seems to affect making plots using knitWord. Code chunks with labels that contain spaces and that don't have plotting commands render normally. knitHTML also seems to work fine regardless of if chunk labels have a space or not.
# Let's make a plot
```{r ugly plot}
plot(btc_prices)
```
should apparently be
# Let's make a plot
```{r ugly_plot}
plot(btc_prices)
```
So no spaces... otherwise you'll waste hours googling and crying.

Subfigures or Subcaptions with knitr?

Is it possible to produce subfigures (with associated subcaptions) using knitr? Here is a minimal working example:
\documentclass{article}
\begin{document}
<<echo = FALSE, fig.cap = c("Some numbers.", "Some more numbers."), out.width = "0.5\\textwidth", fig.align = "center">>=
plot(1:10)
plot(30:100)
#
\end{document}
This results in two figures labelled Figure 1 and Figure 2 with captions as defined (respectively). But I want them to be labelled "Figure 1a" and "Figure 1b", as you can do with the subcaption LaTeX package.
I know there is a knitr options "fig.env", but this doesn't solve it (at least not using, for example, "fig.env = 'subfigure'"). There is a similar post here regarding Sweave, but the solution is an inelegant hack: http://texblog.org/2011/12/01/sweave-subfig-controlling-figure-size-and-placement/
knitr (>= v1.5) supports subfigures. You can use the chunk option fig.subcap. Here is a minimal example.
\documentclass{article}
\usepackage{subfig}
\begin{document}
<<fig-sub, fig.cap='two plots', fig.subcap=c('one plot', 'the other one'), out.width='.49\\linewidth'>>=
plot(1:10)
plot(rnorm(10), pch=19)
#
\end{document}
Updating the answer from Yihui to reflect the changes in Rmarkdown in the past few years, and also the shift away from Rnw files.
As listed within the knitr chunk options, subfigures require a few additional settings to be set in the chunk header:
fig.subcap is a list of the captions for subfigures
fig.ncol: the number of columns of subfigures
out.width: the output width of the figures. You will normally set this 100% divided by the number of sub columns.
Subfigures also require the LaTeX package subfig. The line \usepackage{subfig} must therefore be included within the YAML, or if you are using an external tex template you can add this to that file.
Here is a basic template:
---
output: pdf_document
header-includes:
- \usepackage{subfig}
---
```{r fig-sub, fig.cap='two plots', fig.subcap=c('one plot', 'the other one'), out.width='.49\\linewidth', fig.asp=1, fig.ncol = 2}
plot(1:10)
plot(rnorm(10), pch=19)
```
Using with ggplot2
If you are plotting subfigures which contains multiple ggplot plots, can messy as they do not line up between the plots. You may want to check out this post here on how to use cowplot to force ggplots to have the same dimensions.
This stackoverflow post will help you make sure that all the plots line up as shown in the image below:
Providing a list to subfigures
Just sharing this as a possible extension of subfigures. Something I like to use them for is feeding them a list of figures. Maybe you have produced a function which you need to run on four different trial groups, or in four separate locations. For example, here is a list of four cities in the UK:
```{r}
locations <- c("Southampton, UK", "London, UK", "Bristol, UK", "Birmingham,
```
This list can then be used within the fig.sub and an lapply to produce a list of subfigures. If you need to run the
```{r fig-sub-2, fig.cap='A collection of maps', fig.subcap= locations, out.width='.49\\linewidth', fig.asp=1, fig.ncol = 2}
library(ggmap)
lapply(locations, function(x)
ggmap(get_map(x))
)
```
This makes the subfigures quite robust. If I need to run my model in an extra couple of cities, all I need to do is add extra values to the location list and the sub figures will be the same length.
You can use Latex's subcaption package.
\documentclass{article}
\usepackage{subcaption}
\begin{document}
\begin{figure}
\centering
\begin{subfigure}[b]{0.3\textwidth}
\centering
<<echo = FALSE, out.width = "0.5\\textwidth", fig.align = "center">>=
plot(1:10)
#
\caption{text for first figure}
\label{fig:gull}
\end{subfigure}%
\begin{subfigure}[b]{0.3\textwidth}
\centering
<<echo = FALSE, out.width = "0.5\\textwidth", fig.align = "center">>=
plot(30:100)
#
\caption{text for second figure}
\label{fig:tiger}
\end{subfigure}
\caption{Figure caption}
\end{figure}
\end{document}

Resources