Want to keep the order of figures and text the way you wrote them in R Markdown when you convert to LaTeX? Tired of having to insert \FloatBarrier
after every chunk you want plotted?
Just use knitr
's hooks! Let's look at how we can do it:
First, you need to add the placeins
LaTeX package to the header of your R Markdown file with \usepackage{placeins}
. This lets you use the \FloatBarrier
LaTeX command.
Here's an example YAML header for your R Markdown file:
---
title: "Look Ma, Less Floating!"
date: \today
header-includes:
- \usepackage{placeins}
output: pdf_document
---
Second, you need to add a custom "hook" in knitr
.
Generally, you should probably do that in the first chunks in your file, right after the YAML header. When you make a new .Rmd
file in R Studio, such a chunk is automatically added, called "setup". I sometimes use this chunk to also load my libraries. Here's an example:
```{r setup, include=FALSE, message=FALSE, warning=FALSE}
library(tidyverse)
library(lme4)
knitr::opts_chunk$set(echo = FALSE, cache=FALSE)
```
In order to prevent more floating, you need to include the following at the end of such a chunk:
knitr::knit_hooks$set(plot = function(x, options) {
paste0(knitr::hook_plot_tex(x, options), "\n\\FloatBarrier\n")
})
This effectively pastes \FloatBarrier
after every figure chunk you make, preventing the figures from floating down farther from where you wrote them!
If for some reason you want to be able to change the floating behavior for individual chunks, you can use the following code instead:
knitr::knit_hooks$set(plot = function (x, options) {
float_correct <- function(f, y, opts) {
if (is.null(opts$regfloat) || opts$regfloat==FALSE)
paste0(f(y, opts), "\n\n\\FloatBarrier\n")
else
f(y, opts)
}
if (!is.null(options$out.width) || !is.null(options$out.height) ||
!is.null(options$out.extra) || options$fig.align != "default" ||
!is.null(options$fig.subcap)) {
if (is.null(options$fig.scap))
options$fig.scap = NA
return(float_correct(knitr:::hook_plot_tex, x, options))
}
return(float_correct(knitr:::hook_plot_md_base, x, options))
})
With that code, you can specifiy regfloat=TRUE
in the chunk heading to turn off the automatic \FloatBarrier
.
---
title: "Example Rmd File"
header-includes:
- \usepackage{placeins}
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
knitr::knit_hooks$set(plot = function (x, options) {
float_correct <- function(f, y, opts) {
if (is.null(opts$regfloat) || opts$regfloat==FALSE)
paste0(f(y, opts), "\n\n\\FloatBarrier\n")
else
f(y, opts)
}
if (!is.null(options$out.width) || !is.null(options$out.height) ||
!is.null(options$out.extra) || options$fig.align != "default" ||
!is.null(options$fig.subcap)) {
if (is.null(options$fig.scap))
options$fig.scap = NA
return(float_correct(knitr:::hook_plot_tex, x, options))
}
return(float_correct(knitr:::hook_plot_md_base, x, options))
})
```
## R Markdown
This is just an example `.Rmd` file. Try changing `regfloat=FALSE` to `regfloat=TRUE` for both figure chunks to see how the the hook changes their behavior. In a normal file, you can just leave out the `regfloat` option to have it default to the less floaty behavior.
## The plots
Blah blah blaaaaaaaaaah!
```{r pressure, fig.cap="wowowowow\\label{fig:first-fig}", regfloat=FALSE}
plot(pressure)
```
```{r pressure2, fig.cap="BABABA", regfloat=FALSE}
plot(pressure)
```
## Blag bla blah
This text shouldn't be above the plots when they both have `regfloat=FALSE` (or don't have `regfloat` at all). Blaha fjdsaklfdjsa ofdisafoealkdfjaslkfdjas.