Image footnotes in Bookdown - r

How can I add a figure note right below the image in bookdown::pdf_document2? It is relatively easy to do for plots that created by ggplot2. grid.arrange can do the work with grid.arrange(<plot>, bottom = <figure_notes>). But if I insert an image manually, e.g., knitr::include_graphics(rep("images/knit-logo.png", 3)), is there a way to add a figure note to it? I saw a knitr option, fig.subcap. But this fails to compile:
```{r fig.show="hold", fig.cap = "a", fig.subcap = "b"}
knitr::include_graphics(rep("images/knit-logo.png", 3))
```
This returns:
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (MiKTeX 2.9.6350 64-bit)
entering extended mode
! Undefined control sequence.
<recently read> \subfloat
Error: Failed to compile miniSample.tex. See miniSample.log for more info.
Thanks

If you want to use subfigures, you have to load the subfig package within LaTeX. This can be done by using the header-includes argument in the YAML, as explained here.
Here is a minimal, reproducible example, It creates a local image "temp.jpg" and then produces three subfigures:
---
output: pdf_document
header-includes:
- \usepackage{subfig}
---
```{r}
jpeg(filename = "temp.jpg")
plot(cars)
dev.off()
```
```{r fig.show="hold", fig.cap = "a", fig.subcap = c("Your Caption", "Another Caption", "Isn't this great"), fig.ncol = 3, out.width="33%"}
knitr::include_graphics(rep("temp.jpg", 3))
```
Check out this post for the original description: Subfigures or Subcaptions with knitr?

Found an expedient solution:
Read the image into R using magick::image_read;
Convert the image to raster project with rasterGrob;
Create a note with textGrob; Use grid.arrange to present;
Present the image together with note using grid.arrange.
plot_A <- magick::image_read(<path>) %>% rasterGrob(interpolate = TRUE)
note <- textGrob("This is a note.")
grid.arrange(plot_A, bottom = note)

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.

How do I get Bookdown to properly knit a PDF with multiple code chunks?

I am transitioning to Bookdown from Markdown. Although it seems as though this should be straightforward I am getting an unexpected knit failure once I have added the 3rd (usually) code chunk in a chapter (not index.rmd) file. I have tried using code from the example code by Allaire and Xie with the same result. The problem does not occur if all the markdown code is in one file i.e. no chapters. Here is the sample code from the index and 1st chapter files. Sorry about the formatting; I'm not sure how to format markdown code in stackoverflow so the 3 back tics consistently show.
---
classoption: openany # Removes blank pages (Arrgh!!)
site: "bookdown::bookdown_site"
output:
bookdown::tufte_book2:
latex_engine: xelatex
---
```{r setup, include=FALSE}
library(ggplot2)
# invalidate cache when the tufte version changes
knitr::opts_chunk$set(tidy = FALSE, cache.extra = packageVersion("tufte"))
```
And this is the first chapter code:
# Figures
## Margin Figures
Images and graphics play an integral role in Tufte's work. To place figures in the margin you can use the **knitr** chunk option `fig.margin = TRUE`. For example:
```{r fig-margin, fig.margin = TRUE, fig.cap = "MPG vs horsepower, colored by transmission.", fig.width=3.5, fig.height=3.5, cache=TRUE, message=FALSE}
library(ggplot2)
mtcars2 <- mtcars
mtcars2$am <- factor(
mtcars$am, labels = c('automatic', 'manual')
)
ggplot(mtcars2, aes(hp, mpg, color = am)) +
geom_point() + geom_smooth() +
theme(legend.position = 'bottom')
```
In fact, you can include anything in the margin using the **knitr** engine named `marginfigure`. Unlike R code chunks ```` ```{r} ````, you write a chunk starting with ```` ```{marginfigure} ```` instead, then put the content in the chunk. See an example on the right about the first fundamental theorem of calculus.
```{marginfigure}
We know from _the first fundamental theorem of calculus_ that for $x$ in $[a, b]$:
$$\frac{d}{dx}\left( \int_{a}^{x} f(u)\,du\right)=f(x).$$
```
It fails here
knitr::kable(
mtcars[1:6, 1:6], caption = 'A subset of mtcars.'
)
Deleting the code after "It fails here" makes it knit properly for me.
Dropbox link with scripts, log, and pdf's.

Cross-referencing a table or figure in rmarkdown in the caption of another figure or table

I am producing a rmarkdown document, knitting to PDF and have a figure (figure 1) and a table (table 1) where the table explains the figure in more detail. I have no issue giving either of them a standard caption but I would like to change the table caption to be "Explanation of Figure 1". Is there any way of doing this?
The code chunks are listed below, please let me know if I need to provide more information:
YAML:
- \usepackage{caption} #and several others
output:
bookdown::pdf_document2:
keep_tex: no
latex_engine: xelatex
Code Chunks:
Figure 1:
```{r figure-1, fig.cap="Figure"}
ggplot()
```
Table 1:
```{r table, fig.cap="Explanation of Figure \#ref(fig:figure-1)"}
knitr
kableExtra::kable(caption = "Explanation of Figure \#ref(fig:figure-1)")
```
The main error message with one backslash is "Error: '#' is an unrecognized escape in character string" and suggests I forgot to quote character options, which is not true.
With two backslashes the document knits but produces the caption "Explanation of Figure reffig:table"
3 backslashes: the same error as with 1.
4 backslashes: the error is "pandoc-citeproc: reference ref not found. ! Package caption Error: \caption outside float."
Appreciate any suggestions!
Just a workaround, but may helps.
The \\#ref(fig:xxx) option works well when knitting to a html_document2.
To me pdf - creation worked fine when using pandoc in the terminal.
E.g.:
---
title: "Cross ref"
output:
bookdown::html_document2:
collapsed: no
theme: readable
toc: yes
link-citations: yes
---
```{r firstplot, fig.cap = "A plot with points." }
library(ggplot2)
plot_A = ggplot(data = data.frame(x = c(1:10),
y = seq(3, 8, length.out = 10)),
aes(x = x, y =y))+
geom_point()
plot_A
```
Now a second plot with a reference to Fig.: \#ref(fig:firstplot).
```{r secondplot, fig.cap = "This is the same as Fig.: \\#ref(fig:firstplot)
but now with a red line." }
library(ggplot2)
plot_A + geom_line(alpha = .75,col = "red")
```
after knitting just move to the folder containing the html and using pandoc
pandoc mini_ex-crossref.html -o mini_ex.pdf
I tried many different approaches text references, chunk captions, caption argument in the kable function and I´m sure there is a clever solution somewhere, so here is just a workaround with pure Latex.
Add a latex chunk with a label before the chunk with the figure:
```{=latex}
\begin{figure}
\caption{Figure 1}
\label{Fig-1}
```
```{r figure-1, echo = FALSE}
ggplot(mtcars) +
geom_point(aes(cyl, gear))
```
```{=latex}
\end{figure}
```
Now you can refer to Fig-1 in your latex-caption for the table with normal latex code \ref{Fig-1}:
```{=latex}
\begin{table}
\caption{Explanation of Figure \ref{Fig-1}}
```
```{r table}
kableExtra::kable(x = mtcars)
```
```{=latex}
\end{table}
```
Notes:
* In my opinion this is just a workaround.
* It´s not possible to use the chunk option fig.cap = "" and the latex code in parallel
J_F referenced Yihui Xie's excellent explanation of using text references in RMarkdown (https://bookdown.org/yihui/bookdown/markdown-extensions-by-bookdown.html#text-references), which you can use for figure and table captions that require more complicated things than plain text (e.g., formatting, cross-references, etc.). This may be a more flexible solution overall than remembering to escape the backslash in Robert's answer, and does not require a workaround with LaTeX.
As Yihui explains, all you need to do is define a text reference on a single line in markdown and reference that in the chunk option "fig.cap" or the "caption" parameter in knitr::kable(). Just be careful to make sure that each text reference is one paragraph that does not end in a white space.
Here's a basic example.
---
title: "Cross-referencing figures and tables within captions."
output: bookdown::pdf_document2
editor_options:
chunk_output_type: console
---
```{r load-packages}
library(knitr)
library(flextable)
```
(ref:first-fig-caption) Here's a complicated figure caption for the first figure, which can include complicated text styling like $m^2$ and references to other elements in the document, like Table \#ref(tab:mtcars) or Fig. \#ref(fig:cars).
```{r pressure, fig.cap = '(ref:first-fig-caption)'}
plot(pressure)
```
(ref:second-fig-caption) Here's a second complicated figure caption, also referencing Table \#ref(tab:mtcars).
```{r cars, fig.cap = '(ref:second-fig-caption)'}
plot(cars)
```
(ref:caption-table1) A caption for the first table. Check out this cross reference to Fig. \#ref(fig:pressure).
```{r mtcars}
mtcars |>
head() |>
kable(caption = '(ref:caption-table1)')
```

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

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