为 R Markdown 网站中的每个编织文件使用新环境?

Use new environments for each knitted file in an R Markdown website?

在使用 rmarkdown::render_site() 构建 R Markdown 网站时,似乎每个编织文件都共享相同的环境,并且 knitr/R Markdown 不会为每个单独的页面创建新的空环境。这会导致我无法弄清楚如何摆脱的意外名称空间问题。

例如,以包含以下 5 个文件的最小工作示例为例:

testing.Rproj

Version: 1.0

RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: Sweave
LaTeX: pdfLaTeX

AutoAppendNewline: Yes

BuildType: Website

_site.yml

name: "testing"
navbar:
  title: "Testing"
  left:
    - text: "Home"
      href: index.html
    - text: "Step 1"
      href: 01_something.html
    - text: "Step 2"
      href: 02_something-else.html

index.Rmd

---
title: "Testing"
---

Hello, Website!

01_something.Rmd

---
title: "Step 1"
---

Write some data just for fun.

```{r}
library(tidyverse)
library(here)

write_csv(mtcars, file.path(here(), "cars.csv"))
```

02_something-else.Rmd

---
title: "Step 2"
---

This breaks because `lubridate::here()` and `here::here()` conflict, but *only* when rendering the whole site.

```{r}
library(tidyverse)
library(lubridate)
library(here)

# Do something with lubridate
my_date <- ymd("2018-04-19")

# Try to use here() and it breaks when rendering the whole site
# It works just fine when knitting this file on its own, though, since here is loaded after lubridate
cars <- read_csv(file.path(here(), "cars.csv"))
```

herelubridate 都有一个 here() 函数,因为我想在 02_something-else.Rmd 的整个脚本中使用 lubridate,我运行 library(here)library(lubridate) 之后。 运行 02_something-else.Rmd 以交互方式或自行编排都很好——包加载按正确顺序进行,一切都很好。

但是,当使用 rmarkdown::render_site() 构建站点时(从控制台,从 RStudio 中的 "Build" 按钮,或从终端使用 Rscript -e "rmarkdown::render_site())"),当 R 获取到 02_something-else.Rmd:

Error: '2018-04-19 14:53:59/cars.csv' does not exist in current working directory

R 没有使用 here::here(),而是使用 lubridate::here() 并插入当前日期和时间,因为 library(here) 最初是在 01_something.Rmd 中加载的,而且那个环境似乎当 R 到达 02_something-else.Rmd.

时仍会加载

根据 the documentation for rmarkdown::render_site(),您可以使用 envir = new.env() 参数来确保站点呈现使用新环境,但这并不能解决问题。这似乎保证了整个站点构建过程的新环境,但不是单个文件。

有没有办法确保 R Markdown 网站中的每个单独文件 在编写时都有自己的新环境?

这看起来像是 rmarkdown::render_site 设计中的缺陷,但很容易解决。问题不在于 here 包已加载,问题在于它在搜索列表中。所以你应该删除它。 (从搜索列表中删除东西比卸载它们更容易,而且通常很安全。)

似乎一个很好的防御措施是在每个文档的开头清理您的搜索列表。这个函数是这样做的:

cleanSearch <- function() {
    defaults <- c(".GlobalEnv", 
                  paste0("package:", getOption("defaultPackages")),
                  "Autoloads",
                  "package:base")
    currentList <- search()  
    deletes <- setdiff(currentList, defaults)
    for (entry in deletes)
      detach(entry, character.only = TRUE)       
}

因此,只要在任何库调用之前调用此函数,就可以了。

编辑添加:哎呀,我在评论中看到您已经找到了类似的解决方案。好吧,我的功能看起来比那些更干净,更安全....