I'm trying to cross-reference figures and tables in a PDF produced with knitr/rmarkdown. There are some questions on SO and tex.stackexchange (here and here, for example), that suggest the way to do this inline is to add \ref{fig:my_fig}
, where my_fig
is the chunk label. However, when I try that in my rmarkdown
document, I get ??
where the figure number should be. I'd like to find out how to get cross-referencing to work properly.
A reproducible example is below. There are two files: the rmarkdown
file plus a header.tex
file that I've included just in case it affects the answer (though I have the same problem whether I include the header.tex
file or not).
In the rmarkdown
file there are three cross-reference examples. Example 1 is a figure for which cross-referencing fails (??
is displayed instead of the figure number). There's also a second, commented-out attempt (based on this SO answer), where I try setting the figure environment, label, and caption with latex
markup before and after the chunk, but this results in a pandoc
error when I try to knit the document. The error is:
! Missing $ inserted. <inserted text> $ l.108 ![](testCrossRef_
Example 2 uses xtable
and cross-referencing works. Example 3 uses kable
and cross-referencing fails.
A screenshot of the PDF output is included at the bottom of this post.
rmarkdown
file---
title: |
| My Title
author: |
| eipi10
| Department of Redundancy Department
date: "`r format(Sys.time(), '%B %e, %Y')`"
output:
pdf_document:
fig_caption: yes
includes:
in_header: header.tex
keep_tex: yes
fontsize: 11pt
geometry: margin=1in
graphics: yes
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message=FALSE, warning=FALSE, fig.height=2, fig.width=4)
```
# Example 1. Figure
This is a report. Take a look at Figure \ref{fig:fig1}.
```{r fig1, echo=FALSE, fig.cap="This is a caption"}
plot(mtcars$wt, mtcars$mpg)
```
<!-- Now, let's take a look at this other plot in Figure \ref{fig:fig2}. -->
<!-- \begin{figure} -->
<!-- ```{r fig2, echo=FALSE} -->
<!-- plot(mtcars$cyl, mtcars$mpg) -->
<!-- ``` -->
<!-- \caption{This is another caption} -->
<!-- \label{fig:fig2} -->
<!-- \end{figure} -->
# Example 2: `xtable`
Some more text. See Table \ref{tab:tab1} below.
```{r echo=FALSE, results="asis"}
library(xtable)
print.xtable(
xtable(mtcars[1:3,1:4], label="tab:tab1", caption="An xtable table"),
comment=FALSE)
```
# Example 3: `kable`
Some more text. See Table \ref{tab:tab2} below.
```{r tab2, echo=FALSE}
library(knitr)
kable(mtcars[1:3,1:4], caption="A `kable` table")
```
header.tex
file% Caption on top
% https://tex.stackexchange.com/a/14862/4762
\usepackage{floatrow}
\floatsetup[figure]{capposition=top}
\floatsetup[table]{capposition=top}
To use it, open a Rmd document and, with the cursor within a r chunk and select “Addins –> Insert Table”.
One of the most useful features of LaTeX is its ability to handle cross-references. To use this, we first define a label at the section (or equation, table, etc.) we want to reference, using the \label{} command, e.g. The argument to the \label command is just a text string that you'll use to reference that part.
Cross References In raw markdown, you would for example write a cross-reference to a figure like this: \@ref(fig:label) . Cross-references are largely the same in visual mode, but you don't need the leading \ (which in raw markdown is used to escape the @ character).
You can use the output format bookdown::pdf_document2
instead of pdf_document
, and the syntax for referencing a figure is \@ref(fig:chunk-label)
; see the documentation for details: https://bookdown.org/yihui/bookdown/figures.html
Following I can't generate \label{fig:mwe-plot} with knitr, adding \label{...}
to the caption arguments will produce labels in the underlying tex
file, i.e.
```{r fig1, echo=FALSE, fig.cap="\\label{fig:fig1}This is a caption"}
plot(mtcars$wt, mtcars$mpg)
```
and
```{r tab2, echo=FALSE}
library(knitr)
kable(mtcars[1:3,1:4], caption="\\label{tab:tab2}A `kable` table")
```
You can try the captioner package. You can find examples in this link.
In my case, I include a code chunk with:
table_captions <- captioner::captioner(prefix="Tab.")
figure_captions <- captioner::captioner(prefix="Fig.")
t.ref <- function(label){
stringr::str_extract(table_captions(label), "[^:]*")
}
f.ref <- function(label){
stringr::str_extract(figure_captions(label), "[^:]*")
}
I include captions in tables and figures when defining code chunks, like this:
```{r chunk_creating_one_figure, echo=FALSE, fig.cap=figure_captions("one_figure", "figure label")}
plot(1)
```
or
```{r chunk_creating_one_table, echo=FALSE, fig.cap=table_captions("one_table", "table label")}
knitr::kable(data.frame(col="something"), format="markdown")
```
References are included as inline_text all across my Rmarkdown with:
As shown in figure `r f.ref("one_figure")`
Data is shown on table `r t.ref("one_table")`
After much searching I stumbled on a solution that seems to work (link for this approach), even though I never found it in any of the bookdown standard references (I'll keep looking). Just above the chunk that creates the plot in the .rmd file, define the caption as a string, here called "crossref2" and put the Figure reference in the string in the normal way, \@ref(fig:myChunkLabel)
. No quotes are needed. Here's an example where Fig207 is the chunk label for the figure being referenced:
(ref:crossref2) Variations on boxplot using data from Figure \@ref(fig:Fig207) a) plain violin plot, b) enchanced violin plot, c) add outliers, d) Beeswarm plot
Then in the chunk header for the figure where you want Fig207 to be included in the caption, the figure caption is written as
fig.cap='(ref:crossref2)'
After doing this, the Figure number connected to ref(fig:Fig207) is displayed nicely in the caption.
Note that the same procedure allows you to put a bibliography reference in a figure caption by replacing \@ref(fig:Fig207)
with [@bibref]
where bibref is the keyword for the reference as defined in your .bib file of literature citations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With