用钩子在 knitr/rmarkdown 中用乳胶环境包裹图形

wrapping figure with latex environment in knitr/rmarkdown with hooks

我想使用钩子在 "wrapfigure" 环境中包装使用 knitr 和 rmarkdown 创建的图形。但是,当运行下面的最小示例时,图形块只会被编译成降价图片:

\begin{wrapfigure}{R}{0.3\textwidth}
![](test_files/figure-latex/unnamed-chunk-2-1.pdf) 
\end{wrapfigure}

而不是预期的:

\begin{wrapfigure}{R}{0.3\textwidth}
\includegraphics{test_files/figure-latex/unnamed-chunk-2-1.pdf}
\end{wrapfigure}

最小示例:

---
header-includes:
   - \usepackage{wrapfig}
output: 
  pdf_document:
    keep_tex: TRUE
---

```{r}
library(knitr)
knit_hooks$set(wrapf = function(before, options, envir) {
  if(before) {
    "\begin{wrapfigure}{R}{0.3\textwidth}"
  } else {
    "\end{wrapfigure}"
  }
})
```

```{r, wrapf=TRUE}
library(ggplot2)
qplot(cars$speed, cars$dist)
```

pandoc 负责将 markdown 文档转换为 TEX 文档。由于 pandoc\begin{…}\end{…} 之间没有接触,图像的 markdown 语法没有被转换为 TEX 语法。

你可以……

  • 隐藏情节 (fig.show = 'hide') 并使用 cat("\includegraphics{figure/unnamed-chunk-2-1.pdf}").
  • 中的内容
  • 如上隐藏情节并在保存 cat 的钩子中加入一些魔法。
  • 如果要 PDF 输出,请写 RNW 而不是 RMD。

这是选项 2 的示例:

knit_hooks$set(wrapf = function(before, options, envir) {
  if(before) {
    return("\begin{wrapfigure}{R}{0.3\textwidth}")
  } else {

    output <- vector(mode = "character", length = options$fig.num + 1)

    for (i in 1:options$fig.num) {
      output[i] <- sprintf("\includegraphics{%s}", fig_path(number = i))
    }

    output[i+1] <- "\end{wrapfigure}"
    return(paste(output, collapse = ""))
  }
})

这个钩子可以与 wrapf = TRUEfig.show = "hide" 一起使用。 (另外,header-includes还需要加上\usepackage{graphics}。)

但请注意我不会这样做!在更复杂的环境中,太多事情可能会出错。想想缓存、标题、标签、缓存(再次)…

因此,如果真的需要控制PDF的排版,我推荐写RNW(选项3)。