是否可以创建一个自渲染的 Rmarkdown 文档?

Is it possible to create a self-rendering Rmarkdown document?

对于典型的 R 脚本,shebang 语法可用于 运行 其中的代码。使用文件 file.R

#!/usr/bin/env Rscript

<some R code here>

运行 ./file.R 将执行代码。

但是可以用 R-markdown 做同样的事情吗?因此,使用名为 file.Rmd:

的文件
#!/usr/bin/env <some command>

<some markdown>
<some R code here>
<some markdown again>

运行 ./file.Rmd 会产生 file.md?

Disclaimer: I do not know much about Linux, nor do I have a Linux machine with R installed available to test my answer. Let me know if this does not work properly. If this inspires someone to write a better answer, I'll happily delete this one.


让我倒退一下:

  • 编织文档,我们需要调用rmarkdown::render()
  • 从命令行到运行这个命令,我们可以使用RScript -e "rmarkdown::render('document.Rmd')",参见例如.
  • 可能你 do not want to hardcode the path to Rscript 但改用像 #!/usr/bin/env Rscript 这样的 shebang。
  • 这种方法的问题在于 it does not allow to pass arguments to Rscript
  • 因此我建议在 shebang 中使用一个“包装器”来负责调用 Rscript
  • 将RMD文件名设为argument,所需R代码变为rmarkdown::render(commandArgs(trailingOnly=TRUE)[1]).

一步一步:

  1. 创建包装器(在您的 $PATH 中的任何目录中)和 make it executable:

     touch KnitWrapper.sh
     chmod +x KnitWrapper.sh
    
  2. 将以下内容写入KnitWrapper.sh:

     #!/usr/bin/env bash
     Rscript -e "rmarkdown::render(commandArgs(trailingOnly=TRUE)[1])" 
    
  3. 确保 Rscript 在您的 $PATH 中。如果您更新 R,请相应地更新您的 $PATH

  4. 在您的 RMD 文件中,添加 shebang #!/usr/bin/env KnitWrapper.sh

  5. 使您的 RMD 文件可执行并 运行 它:

     chmod +x yourDocument.Rmd
     ./yourDocument.Rmd
    

不幸的是,以上大部分未经测试。如果它不起作用,请告诉我,以便我修复或删除此答案。

您可以将 Rmd 文件视为 Rscript。例如,假设你的 Rmd 文件看起来像这样

---
title: "Untitled"
author: "ekoam"
date: "`r Sys.Date()`"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

## R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.

When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

```{r cars}
summary(cars)
```

## Including Plots

You can also embed plots, for example:

```{r pressure, echo=FALSE}
plot(pressure)
```

Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.

然后您可以将以下代码添加到该 Rmd 文件中

#!/usr/bin/env Rscript

args <- commandArgs()
fname <- normalizePath(sub("--file=", "", args[grepl("--file=", args)]))
thisfile <- readLines(fname)
newfname <- paste0(tempdir(), "/", basename(fname))
writeLines(thisfile[-1:-which(thisfile == "q(\"no\")")], newfname)
rmarkdown::render(newfname, output_dir = dirname(fname))
q("no")

这里的技巧是q("no")。这一行终止了 R 会话,因此,它之后写入的任何内容都将被忽略。这样的效果也意味着编码的高度灵活性,因为您可以在此之前编写几乎任何有效的 R 代码 q("no")。上面的代码只是创建了另一个临时 Rmd 文件,其内容与 q("no") 之后的内容相同。然后,我们 rmarkdown::render 该临时文件并将输出转储到当前目录。

完整的 Rmd 文件如下所示

#!/usr/bin/env Rscript

args <- commandArgs()
fname <- normalizePath(sub("--file=", "", args[grepl("--file=", args)]))
thisfile <- readLines(fname)
newfname <- paste0(tempdir(), "/", basename(fname))
writeLines(thisfile[-1:-which(thisfile == "q(\"no\")")], newfname)
rmarkdown::render(newfname, output_dir = dirname(fname))
q("no")

---
title: "Untitled"
author: "ekoam"
date: "`r Sys.Date()`"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

## R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.

When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

```{r cars}
summary(cars)
```

## Including Plots

You can also embed plots, for example:

```{r pressure, echo=FALSE}
plot(pressure)
```

Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.