使用opts_chunk$set(root.dir = ...)在knitr中设置工作目录无效。

49
我的 R 项目结构类似于一个包,其中包括目录 /R/vignettes/data 等等。在我位于 /vignettes 的一个 Rmd 文档中,我调用了位于 /R 中的脚本。在这个脚本中,我使用 read.csv() 来加载一个位于 inst/extdata/ 的文件。
现在的问题是,在 Rmd 文件中默认的工作目录是该文件所在的目录。让我们称其为 /Users/Me/Docs/Proj/vignettes。然而,为了使 R 脚本能够运行,需要将工作目录设置为项目的主目录(/Users/Me/Docs/Proj)。
我尝试使用 knitr::opts_chunk$set(root.dir = normalizePath("..") 在 Rmd 文件中更改工作目录。然而,显然这并没有改变工作目录,因为如果我在此之后调用 getwd(),输出仍然是/Users/Me/Docs/Proj/vignettes,而 knitr::chunk_opts$get("root_dir") 返回/Users/Me/Docs/Proj

这里有一个最小化的 Rmd 文件示例:

```{r}
getwd()  # returns 'Users/Me/Docs/Proj/vignettes'
knitr::opts_chunk$set(root.dir = normalizePath(".."))  # should change the working directory to 'Users/Me/Docs/Proj'
getwd()  # again returns 'Users/Me/Docs/Proj/vignettes'
knitr::opts_chunk$get("root.dir")  # returns 'Users/Me/Docs/Proj'
```

我正在使用RStudio版本0.99.435。下面是我的会话信息:

R version 3.2.0 (2015-04-16)  
Platform: x86_64-apple-darwin14.3.0 (64-bit)  
Running under: OS X 10.10.3 (Yosemite)  

locale:
[1] de_DE.UTF-8/de_DE.UTF-8/de_DE.UTF-8/C/de_DE.UTF-8/de_DE.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] htmltools_0.2.6 tools_3.2.0     yaml_2.1.13     rmarkdown_0.6.1 digest_0.6.8   

非常感谢您提供的任何帮助。如果您需要更多信息,请在问题下发表评论。提前致谢!


为什么不直接使用 setwd() 函数呢? - Stibu
7
knitr::knit 的文档中可以得知:"不建议在代码块中通过 'setwd()' 更改工作目录,因为这可能会导致可怕的后果(例如图形和缓存文件可能被写入错误的位置)。如果您确实使用 'setwd()',请注意,'knitr' 将始终将工作目录还原为原始目录。" - Thomas Neitmann
7个回答

45

如果您有一个具有嵌套子文件夹的R项目,以便 .Rproj 和 .Rmd 文件位于不同的文件夹中,您可以使用命令rprojroot::find_rstudio_root_file() 在Kniting期间找到并将工作目录设置为项目的主文件夹(而不是包含rMarkdown代码文件的文件夹)。

因此,至少使用以下内容:

```{r setup}

knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file())

```

setup代码块内部。

另请参阅在R Studio中自动查找当前R项目路径


这太棒了!=) - radek
这是解决这个问题的最佳方式。 - Óscar Gómez Alcañiz

42

4
这在Linux下的RStudio 1.0.143中有效,但仅限于{r setup}...代码块中。将其命名为{r initialization}...会导致其失效。 - mightypile

23
正如Yihui在他的回答中指出的那样,错误只是我使用了opts_chunk$set()而不是opts_knit$set()
然而,值得注意的是,工作目录的更改只会影响下一个块,而不是当前块。因此,例如,如果您想要相对于新的工作目录加载数据,请在下一个块中执行。

10

关于通过 root.dir = 设置工作目录的实现细节。


尽管YihuiTommy已经有一些非常好的答案,但我仍然在设置工作目录时遇到了困难。所以我在这里尝试提供一个完整的答案。

  1. 来自knitr文档

必须在任何依赖于这些设置处于活动状态的块之前在一个块中设置knitr的设置。建议创建一个knit配置块作为脚本中的第一个块,并设置选项cache = FALSE和include = FALSE。该块不得包含任何命令,这些命令要求配置块中的设置在执行时处于有效状态。

  1. 我的代码示例:

在我的情况下,.Rproj.Rmd文件位于同一文件夹中。

```{r setup, include=FALSE, cache = FALSE}
require("knitr")
## setting working directory
opts_knit$set(root.dir = "~/Documents/R/Example")
```

我在笔记本设置工作目录时遇到了相同的问题(RStudio 1.2.1335,R 3.5.3),尽管@Yihui和@Tommy的回答,由于_setup-chunk_内部的getwd()命令。感谢@Guannan澄清了解决方案! - Gregor Kvas

3

对于我来说,knitr::opts_knit$set 可以与 root.dir 一起使用,但不能与 echo = FALSE 一起使用。

然而,

knitr::opts_chunk$set 可以与 echo = FALSE 一起使用,但不能与 root.dir 一起使用。

因此,

我在设置块中同时使用了这两个选项:

```{r settings, include = FALSE}

knitr::opts_chunk$set(echo = FALSE
                      , comment = NA
                      , warning = FALSE
                      , error = FALSE
                      , message = FALSE
                      , tidy = TRUE)

knitr::opts_knit$set(root.dir = 'C:/...')

```

如果你在这里看 https://yihui.org/knitr/options/#package-options,你会发现目录中有两个块叫做“代码块选项”和“包选项”。我刚刚意识到它们是关于你的困惑。我也曾经有同样的困惑。 - Sergey Skripko

0

以下代码块需要作为 Rmd 脚本的第一个代码块。

{r setup, include=FALSE, cache = FALSE}
knitr::opts_knit$set(
  root.dir = rprojroot::find_rstudio_root_file()
  )

但是,有时它不起作用。我发现可能是由于块输出设置引起的。块内联输出块控制台输出是不同的。请确保块内联输出和设置块将正常工作。


0

当我把.Rmd文件放在其他文件的上游子目录中时,我无法让knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file())setup块中与knitr::include_graphics一起工作(对于source()load()可以正常工作)。如果你遇到同样的问题,请尝试:

library(here)
knitr::include_graphics(here("figs/figure.png"))

在这些情况下,您显然也可以使用../,但是在调试时,路径将无法直接在控制台中工作。

解决方案来源:https://community.rstudio.com/t/knittr-include-graphics-image-png-cannot-find-files/82959/2


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