在从主文件.R中编织.Rmd文件时,找不到.rmd块中的文件源问题。

4
假设我有一个项目目录,叫做"testknit"(实际上就是这个名字,可参考MRE的github), 目录下包含多个子目录,其中包括一个"scripts"目录,用于存储".R"和".rmd"文件。
在RStudio中,我创建了一个项目并选择了"testknit"目录,这样当我打开项目时,工作目录就是"mypath/testknit"。
在"testknit/scripts"目录中,我有一个"master.R"文件。如果我想要引用一个名为"testsource1.R"的文件,它也在"testknit/scripts"目录中,我可以在"master.R"文件中运行"source("scripts/testsource1.R")"。
library(knitr)
getwd()
# [1] "mypath/testknit"
source("scripts/testsource1.R")

到目前为止,一切都很好。
但是假设我还想编织一个名为 test.rmd 的文件,它位于 testknit/scripts 中。 我可以从 master.R 运行 knit("scripts/test.rmd")
我的 test.rmd 文件执行以下操作:
```{r setup}
  library(knitr)
  opts_knit$set(root.dir='../')
```

```{r option1}
  source("scripts/testsource2.R")
```

```{r option2}
  source("testsource2.R")
```

自从test.rmd存在于testknit/scripts中,因此我在第一个代码块中指定opts_knit$set(root.dir='../'),以便knitr知道我的根目录实际上是向上一级。
当我在RStudio中打开test.rmd并单击knit HTML时,显然option1代码块可以工作而option2代码块无法工作。
但是,当我尝试从master.R运行knit("scripts/test.rmd")而不是从.rmd文件中编织时,两个选项都无法正常工作。两者都返回找不到该名称的文件的错误。
我做错了什么?为什么在从主.R中编织.rmd文件时R找不到testsource2.R
请参见上面的github链接以获取可重现的示例。
更新:
如我在下面的评论中所述,我尝试在opts_knit$set之前添加wd <- getwd()并将(root.dir='../')更改为(root.dir=wd)。因此,当我从master.R运行knit("scripts/test.rmd")时,由于我添加的wd被设置为mypath/testknit/scripts,因此选项2代码块运行。但是,如果我打开.rmd文件并运行所有代码块,则wd将设置为根目录mypath/testknit,并且选项1代码块将运行。
我需要工作目录保持项目根目录。对我来说,这似乎不是一种优雅的解决方案,但更改:
```{r setup}
  library(knitr)
  opts_knit$set(root.dir='../')
```

to

```{r setup}
  library(knitr)
  wd <- ifelse(basename(getwd())=="scripts", 
               gsub("/scripts", "", getwd()),
               getwd())
  opts_knit$set(root.dir=wd)
```

当我在.rmd文件中或从master.R运行knit("scripts/test.rmd")时,可以让我运行所有块。这种方法虽然可行,但感觉并不是最佳选择。


不知道,但为什么不通过在每个代码块中添加getwd()调用来进一步检测你的.rmd文件呢? - Ben Bolker
@BenBolker,我在opts_knit$set(root.dir=wd)之前添加了wd <- getwd()。我不知道为什么,但现在当我从master.R运行knit("scripts/test.rmd")时,wd被设置为mypath/testknit/scripts,因此option2块运行。但是,如果我打开.rmd文件并运行所有块,则wd设置为根目录mypath/testknit,并且option1块运行。你知道为什么从master.R运行knit("scripts/test.rmd")时,wd会从mypath/testknit更改为mypath/testknit/scripts吗? - Eric Green
也许您可以使用 normalizePath('../')../ 转换为绝对路径。相对工作目录可能会让人感到困惑(至少我在阅读太多级别的相对路径后会感到头痛 :)。顺便说一下,当您在 RStudio 中编织 HTML 时,RStudio 首先将工作目录更改为输入的 Rmd 文件所在目录。 - Yihui Xie
没问题。只要让我知道这个瞎猜是否有效 :) - Yihui Xie
是的!只需使用opts_knit$set(root.dir=normalizePath('../'))就可以从master.R中编织.rmd文件并将其编织为html或从.rmd内运行所有块。我更新了GitHub示例。test-b.rmd现在显示了这一点。谢谢!如果您创建一个答案,我会选择它。 - Eric Green
1个回答

4

@Yihui: 或许你可以使用 normalizePath('../')../ 转换成绝对路径。相对工作目录可能会让人感到困惑(我至少看了太多级别的相对路径之后头痛)。顺带一提,当你在 RStudio 中编织 HTML 时,RStudio 会首先将工作目录更改为输入的 Rmd 文件。

我:是的!只需要使用 opts_knit$set(root.dir=normalizePath('../')) 即可从 master.R 编制 .rmd 文件,并将其编织为 HTML 或在 .rmd 中运行所有块。我已经更新了github 示例。现在,test-b.rmd 显示出这一点。谢谢!


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