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

时间:2020-10-23 18:20:42

标签: r r-markdown knitr executable shebang

对于典型的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吗?

2 个答案:

答案 0 :(得分:5)

您可以将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会话,因此,它将忽略它之后写入的所有内容。这样的效果还意味着编码的高度灵活性,因为您可以在q("no")之前编写几乎任何有效的R代码。上面的代码只是创建另一个临时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.

答案 1 :(得分:2)

免责声明:我对Linux不太了解,也没有安装R的Linux机器来测试我的答案。让我知道这是否无法正常工作。如果这能激发某人写一个更好的答案,我会很乐意删除此答案。


让我向后退一步:

  • 要编织文档,我们需要调用rmarkdown::render()
  • 要从命令行运行此命令,我们可以使用RScript -e "rmarkdown::render('document.Rmd')",例如here
  • 可能是您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])" $1
    
  3. 确保Rscript在您的$PATH中。如果您更新R,请相应地更新$PATH

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

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

     chmod +x yourDocument.Rmd
     ./yourDocument.Rmd
    

不幸的是,以上内容未经测试。让我知道它是否无效,因此我可以修复或删除此答案。