How to hold figure position with figure caption in pdf output of knitr?
RKnitrR MarkdownR Problem Overview
I am using knitr (1.9.5 and 1.9.17) and rmarkdown (0.5.3.1), and would like to hold figure position in the pdf output. The generated pdf file is working fine when chunk option fig.pos="H"
is used.
However, the figure position is not hold when fig_caption: yes
is set in the
yaml header.
How should I fix this problem? Thanks for any suggestions.
EDIT:
After learning the float environment of Latex. I add float
package into header.
\usepackage{float}
But the generated tex file always use htbp
in the figure
environment regard to any fig.pos
options are used. After manually changing htbp
to H
, positions of all figures are hold.
This is my example of rmd file:
---
title: "Untitled"
output:
pdf_document:
fig_caption: yes
includes:
in_header: mystyles.sty
---
# Section 1
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
```{r fig1, echo=FALSE, fig.height=8.5, fig.pos="H"}
plot(cars)
```
# Section 2
More test
```{r fig2, echo=FALSE, fig.height=8.5, fig.pos="H"}
plot(cars)
```
# Section 3
```{r fig3, echo=FALSE, fig.height=8.5, fig.pos="H"}
plot(cars)
```
More test
R Solutions
Solution 1 - R
For me adding the float
package and then \floatplacement{figure}{H}
in YAML solved the issue like :
---
title: "test"
date: "`r Sys.Date()`"
output:
pdf_document :
keep_tex: true
number_sections: true
header-includes:
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{array}
\usepackage{multirow}
\usepackage[table]{xcolor}
\usepackage{wrapfig}
\usepackage{float}
\floatplacement{figure}{H}
---
Solution 2 - R
As Andrew pointed out, this fig.pos
doesn't work in chunks, but it does work if it is put in global options:
```{r global_options, include=FALSE}
knitr::opts_chunk$set(fig.pos = 'H')
```
EDIT: the above apparently used to work and needs \usepackage{float}
in the preamble:
header-includes:
\usepackage{float}
Solution 3 - R
Update look at this better solution here. (the summary of the problem below is still good, but follow the link to a better solution).
To summarise some testing in RStudio
The knitr chunk argument fig.pos = "H" works as long as fig_caption: yes
is not in the yaml header.
Each figure in the generated .tex looks like this
\subsection{my_section}\label{my_section}
\includegraphics{path_to_fig.pdf}
But if fig_caption: yes
is in the yaml header then the .tex looks like this
\subsection{my_section}\label{my_section}
\begin{figure}[htbp]
\centering
\includegraphics{path_to_fig.pdf}
\caption{}
\end{figure}
fig.pos = "H"
has not been used, "htbp"
is there instead.
A workaround for this using RStudio:
put
fig_caption: yes
keep_tex: yes
in the yaml as well as
header-includes: \usepackage{float}
then search and replace [htbp]
with [H]
in the generated .tex file
then open the .tex file in RStudio and use the "Compile PDF" button.
Example .Rmd
---
title: "Testing fig placement with captions"
author: "Andrew Dolman"
date: "1 September 2015"
output:
pdf_document:
fig_caption: yes
keep_tex: yes
header-includes: \usepackage{float}
---
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}
summary(cars)
```
You can also embed plots, for example:
```{r, echo=FALSE, fig.pos="H"}
plot(cars)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
```{r, echo=FALSE, fig.pos="H"}
plot(cars)
```
Solution 4 - R
Although the answer provided by @Bangyou works, it complicates knitting.
You can also set a global default option for figure placement in latex, including this in your YAML header includes:
\makeatletter\renewcommand*{\fps@figure}{H}\makeatother
As explained here (and here for the \makeat...
part).
This way you can just use the knit button in RStudio or rmarkdown::render and be done with it.
Issue is, all figures fill be forced with H and you won't be able to set one to float around.
Solution 5 - R
The option that worked for me:
In the .tex put at the beginning: \usepackage{float}
.
At the beginning of the Rmd: knitr::opts_chunk$set(fig.pos = 'H')
. The H
in upper case).
And in every chunk with an image: fig.cap="lorem blabla"
and out.extra=''
(parameter value=empty string).
No need to define:
fig_caption: yes
and keep_tex: yes
in the yaml.
These options make the image to keep their position, either for include_graphics
and the plots generated by R code.
I used them in the bookdown
enviroment, generating the pdf and the html as expected :)
Solution 6 - R
The code from https://stackoverflow.com/questions/16626462/figure-position-in-markdown-when-converting-to-pdf-with-knitr-and-pandoc/33801326#33801326 helps me, help anyone else find it useful.
---
title: "Example"
author: "Martin"
output: pdf_document
---
```{r}
knitr::knit_hooks$set(plot = function(x, options) {
knitr::hook_plot_tex(x, options)
})
```
```{r myplot, echo=FALSE, results='hide', fig.cap='Test', fig.pos='h'}
library(ggplot2)
ggplot(mtcars, aes(mpg, drat)) + geom_point()
```
Solution 7 - R
As Yihui mentioned in his answer (https://stackoverflow.com/questions/16626462/figure-position-in-markdown-when-converting-to-pdf-with-knitr-and-pandoc), we cannot expect too much about formatting from mardown. To workaround this problem, just write some R scripts to replace htbp
to H
.
Compared with knit
from knitr package, I found render
from rmarkdown is better to export a tex
file. Just remember to add keep_tex: yes
in the yaml header of your rmarkdown file.
library(rmarkdown)
render('filepath.Rmd')
x <- readLines('filepath.tex')
pos <- grep('begin\\{figure\\}\\[htbp\\]', x)
x[pos] <- gsub('htbp', 'H', x[pos])
writeLines(x, 'filepath.tex')
tools::texi2pdf('filepath.tex', clean = TRUE) # gives foo.pdf
file.remove('filepath.tex')