knitr/rmarkdown/Latex:如何交叉引用图表?

69
我试图在由knitr/rmarkdown生成的PDF中交叉引用图和表。有一些关于SO和tex.stackexchange(例如这里这里)的问题建议内联使用\ref{fig:my_fig},其中my_fig是块标签的方式来实现此功能。然而,当我在我的rmarkdown文档中尝试时,在应显示图形编号的位置上会出现??。我想找出如何使交叉引用正常工作。

以下是一个可重现的示例。有两个文件:一个rmarkdown文件和一个header.tex文件,我包含它只是为了防止影响答案(尽管我无论是否包含header.tex文件都存在同样的问题)。

rmarkdown文件中,有三个交叉引用示例。示例1是一个图形,交叉引用失败(应显示??而不是图形编号)。还有第二个被注释掉的尝试(基于这个SO答案),在这里我尝试在块之前和之后使用latex标记设置图形环境、标签和标题,但当我尝试编织文档时,这会导致一个pandoc错误。该错误是:

! Missing $ inserted.
<inserted text> 
                $
l.108 ![](testCrossRef_
例子2使用xtable并且交叉引用起作用。例子3使用kable并且交叉引用失败。
这篇文章底部包含PDF输出的截屏。 文件
---
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 文件

% Caption on top
% https://tex.stackexchange.com/a/14862/4762
\usepackage{floatrow}
\floatsetup[figure]{capposition=top}
\floatsetup[table]{capposition=top}

PDF 输出

输入图片描述


11
这个问题似乎已经在这里讨论过:我无法使用knitr生成\label{fig:mwe-plot}。硬编码{r fig1, echo=FALSE, fig.cap="\\label{fig:fig1}This is a caption"}似乎有效。 - Weihuang Wong
4个回答

52

4
有没有一种方法与自定义的 rmarkdown 格式兼容,例如来自 rticles 模板? - cboettig
3
可以更改 base_format 到任何包中的输出格式函数。参考链接:https://bookdown.org/yihui/bookdown/latexpdf.html。 - Yihui Xie
1
Yihui在上面的回答似乎不能用于bookdown::tufte_book2。当输出格式更改为tufte_book2时,以pdf_document2正确显示的图表交叉引用会显示为“??”。 - Moonhawk
3
据我所知,似乎无法更改bookdown::pdf_document2的base_format,但应该使用bookdown::pdf_book代替。来源:https://dev59.com/Iq7la4cB1Zd3GeqPf52D#52480807 - julou
1
@JamesHirschorn render_bookbookdown 的函数,在 rmarkdown 中,你可以使用 render 并将 bookdown::pdf_document2 作为 output_format 参数传递,例如:rmarkdown::render("Index.Rmd", output_format = bookdown::pdf_document2") - Trusky
显示剩余2条评论

44

根据我无法用knitr生成\label{fig:mwe-plot} ,将\label{...}添加到标题参数中将在底层的tex文件中生成标签,即:

```{r fig1, echo=FALSE, fig.cap="\\label{fig:fig1}This is a caption"}
plot(mtcars$wt, mtcars$mpg)
```
```{r tab2, echo=FALSE}
library(knitr)
kable(mtcars[1:3,1:4], caption="\\label{tab:tab2}A `kable` table")
```

@Yihui,由于这是基于一个两年前的答案,现在这仍然是最先进的技术吗?还是有更好的方法来实现这个功能? - eipi10
现在有更好的方法。简而言之,使用bookdown::pdf_document2代替pdf_document;请参见https://bookdown.org/yihui/bookdown/figures.html - Yihui Xie
3
这个解决方案的优点是它不依赖于bookdown。 - jjj

3
你可以尝试使用captioner包。你可以在this link中找到示例。
在我的情况下,我包含了一个代码块:
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), "[^:]*")
}

在定义代码块时,我会在表格和图像中包含说明文字,就像这样:

```{r chunk_creating_one_figure, echo=FALSE, fig.cap=figure_captions("one_figure", "figure label")}
plot(1)
```

或者

```{r chunk_creating_one_table, echo=FALSE, fig.cap=table_captions("one_table", "table label")}
knitr::kable(data.frame(col="something"), format="markdown")
```

参考文献以内联文本的形式包含在我的Rmarkdown中:

As shown in figure `r f.ref("one_figure")`
Data is shown on table `r t.ref("one_table")`

1
现在是2022年4月,我仍然找不到如何在bookdown :: tufte_book2中引用另一个图的标题中的图的答案。 在过去的6年中,我尝试了我能找到的每个建议,但似乎没有一种方法可行。 有人知道实现此功能的权威指南吗? 这就是我想要做的事情 其中Fig607在代码块中已经定义。 结果是标题以'from '结束。 - Dr Dave

1

经过多次搜索,我偶然发现了一个看起来可行的解决方案(链接),尽管我在任何bookdown标准参考书中都没有找到它(我会继续寻找)。在创建.Rmd文件中绘制图表的代码块上面,将标题定义为字符串,在这里称为“crossref2”,并以正常方式将图表引用放入该字符串中,例如\@ref(fig:myChunkLabel)。不需要引号。这是一个例子,其中Fig207是所引用图表的代码块标签:

(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

然后,在包含Fig207的标题的图块头部,图的标题应写为:

fig.cap='(ref:crossref2)'  

完成此操作后,与 ref(fig:Fig207) 相关联的图形编号将在标题中得到良好显示。
请注意,同样的过程允许您在图形标题中放置参考文献引用,方法是将 \@ref(fig:Fig207) 替换为 [@bibref],其中 bibref 是在文献引用的 .bib 文件中定义的关键字。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接