Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knitr/rmarkdown/Latex: How to cross-reference figures and tables?

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}

PDF output

enter image description here

like image 766
eipi10 Avatar asked Aug 09 '16 21:08

eipi10


People also ask

Can you insert a table into R markdown?

To use it, open a Rmd document and, with the cursor within a r chunk and select “Addins –> Insert Table”.

How do you cross reference in LaTeX?

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.

How do you cross reference in markdown?

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).


4 Answers

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

like image 134
Yihui Xie Avatar answered Oct 21 '22 17:10

Yihui Xie


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")
```
like image 30
Weihuang Wong Avatar answered Oct 21 '22 16:10

Weihuang Wong


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")`
like image 3
Gitanoqevaporelmundoentero Avatar answered Oct 21 '22 16:10

Gitanoqevaporelmundoentero


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.

like image 1
Dr Dave Avatar answered Oct 21 '22 17:10

Dr Dave