为什么从 rmarkdown 渲染 pdf 需要在渲染之间关闭 rstudio?

Why does rendering a pdf from rmarkdown require closing rstudio between renders?

背景

我正在尝试制作一个使用 render() 呈现的 rmarkdown 文档。 render 调用有两个参数化的元素:

这是名为 test.Rmd

的 rmarkdown 文件
---
title: "Title"
author: "Zzz Zzzzzz"
params:
  table_format:
    value
---

```{r setup}
knitr::opts_chunk$set(echo = FALSE)
library(knitr)
library(kableExtra)

options(knitr.table.format = params$table_format) 
```

## Test table

```{r cars}
if (params$table_format == "latex"){
kable(iris[1:100,], booktabs = T) %>%
  kable_styling(latex_options = c("scale_down")) 
}

if (params$table_format == "html"){
kable(iris[1:100,]) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))  %>%
  scroll_box(width = "500px", height = "600px")
}


params$table_format
```

下面是渲染文件的两个调用:

rmarkdown::render("test.Rmd", output_format = "pdf_document", params = list(
  table_format = "latex"
))


rmarkdown::render("test.Rmd", output_format = "html_document", params = list(
  table_format = "html"
))

问题

现在,如果我打开一个新的 rstudio 会话,我可以 运行 两个 render 调用都没有问题。创建 .pdf 或 .html 文件。但是,如果我随后尝试 运行 .pdf 渲染 再次 我收到以下错误:

"C:/Program Files/RStudio/bin/pandoc/pandoc" +RTS -K512m -RTS test.utf8.md --to latex --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output test.pdf --template "C:\Users\salbers\R\win-library.4\rmarkdown\rmd\latex\default-1.17.0.2.tex" --highlight-style tango --latex-engine pdflatex --variable graphics=yes --variable "geometry:margin=1in" ! Undefined control sequence. \begin {tabular}{rrrrl} \toprule Sepal.Length & Sepal.Width & Pet... l.267 \end{tabular}}

pandoc.exe: Error producing PDF Error: pandoc document conversion failed with error 43 In addition: Warning message: running command '"C:/Program Files/RStudio/bin/pandoc/pandoc" +RTS -K512m -RTS test.utf8.md --to latex --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output test.pdf --template "C:\Users\salbers\R\win-library.4\rmarkdown\rmd\latex\default-1.17.0.2.tex" --highlight-style tango --latex-engine pdflatex --variable graphics=yes --variable "geometry:margin=1in"' had status 43

html 渲染一次又一次地正常工作。如果我关闭 rstudio,然后打开项目,pdf 的渲染也可以正常工作。

问题

2019-01-21 更新:

knit button 和 render 函数的最大区别之一是,knit button 总是以 "new environment" 开头(我们都可以感觉到),而 render 函数默认在 parent.env() 开始。

render(input, ..., envir = parent.frame(), ...)

在函数文档中,我们看到

envir   
The environment in which the code chunks are to be evaluated 
during knitting (can use new.env() to guarantee an empty new 
environment).

因此,我们可以通过在渲染调用中放入 envir = new.nev() 来模拟单击 knit 按钮的行为。


原答案:

嗯,我先post解决。要解决此问题,您需要将以下内容放入您的 yaml 部分。我还在本周早些时候的开发版本中添加了一个功能 kableExtra_latex_packages() 来调出以下文本。

header-includes:
  - \usepackage{booktabs}
  - \usepackage{longtable}
  - \usepackage{array}
  - \usepackage{multirow}
  - \usepackage[table]{xcolor}
  - \usepackage{wrapfig}
  - \usepackage{float}
  - \usepackage{colortbl}
  - \usepackage{pdflscape}
  - \usepackage{tabu}
  - \usepackage{threeparttable}
  - \usepackage[normalem]{ulem}

如果您好奇为什么会出现这种奇怪的行为,这里有一个简短的解释。当您第一次在 rmarkdown 环境中加载 kableExtra 时,它将 try to put the LaTeX package information above into the rmarkdown metadata using the usepackage_latex() function 随此软件包一起提供。如果你只是点击编织按钮,它就可以正常工作,因为每个 "knit+rendering" 进程都应该被隔离。然而,令人惊讶的是(顺便说一句,谢谢你提出来),正如我们在这里看到的那样,如果你试图从控制台渲染,因为(我的假设)knitr 或 rmarkdown 试图重用一些缓存的结果,这个过程无法复制。事实证明,这些 LaTeX 包依赖项没有放入正在生成的 tex 文件中,并以错误结束。如果您关闭 RStudio 并重新启动它,当然,它拥有的临时内存将会消失,您应该能够再次加载这些包。我觉得这可能是 rmarkdown 中与全局变量相关的错误。我想我们可以通过在 render 函数的末尾添加一个 "forget the meta" 部分来修复它,但我需要这样看。

部分原因是我没有提供足够的关于过去版本中使用的 LaTeX 包的文档。现在,我在本周早些时候发布的 kableExtra 0.5.0 package vignette 的开头添加了一个关于这个问题的新部分。请随时查看。另外,正如我之前所说,在当前的开发版本中,您可以使用函数 kableExtra_latex_packages() 调出列表。

就我而言,@Hao 的回答没有用...我终于设法在每次渲染执行后卸载 kableExtra 包,如下所示:

rmarkdown::render('torender.Rmd')
detach("package:kableExtra", unload=TRUE)

应该也可以使用类似

的方式选择环境
rmarkdown::render('torender.Rmd',envir=new.env(some parameters))

哪个更干净....但我没有这样做!

我有一个类似的问题:循环呈现包含 table 的 PDF 报告。 PDF 无法使用 booktabs = T 呈现。我的解决方案是在从循环调用的 Rmd 脚本中手动加载我的设置块中的所有乳胶包。

所以在多次调用的 Rmd 脚本中我有:

usepackage_latex("booktabs")
usepackage_latex("longtable")
usepackage_latex("array")
usepackage_latex("multirow")
usepackage_latex("xcolor", "table")
usepackage_latex("wrapfig")
usepackage_latex("float")
usepackage_latex("colortbl")
usepackage_latex("pdflscape")
usepackage_latex("tabu")
usepackage_latex("threeparttable")
usepackage_latex("threeparttablex")
usepackage_latex("ulem", "normalem")
usepackage_latex("makecell")

这解决了问题 - 使用格式化 tables.

呈现的 PDF

希望这对某人有所帮助。

我发现一个对多个 .Rmd 文件执行此操作的简单方法是使用这些 kableExtra-added \usepackage{} 命令的列表创建一个 "headers.tex" 文件。然后在 .Rmd 文件的 YAML 头中:

output: 
  pdf_document:
    includes:
      in_header: headers.tex

这是我放在 header.tex 文件中的内容——我从一个有效的文件中复制了它,它也是 kableExtra_latex_packages() 剥离 "header-includes:" 的输出线和破折号。

\usepackage{booktabs}
\usepackage{longtable}
\usepackage{array}
\usepackage{multirow}
\usepackage{wrapfig}
\usepackage{float}
\usepackage{colortbl}
\usepackage{pdflscape}
\usepackage{tabu}
\usepackage{threeparttable}
\usepackage{threeparttablex}
\usepackage[normalem]{ulem}
\usepackage{makecell}
\usepackage{xcolor}