【问题标题】:Is it possible to create a self-rendering Rmarkdown document?是否可以创建一个自渲染的 Rmarkdown 文档?
【发布时间】:2020-10-23 18:20:42
【问题描述】:

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

【问题讨论】:

  • 为什么不在 Rmd 文档上调用rmarkdown::render 的脚本?否则我不确定文件如何知道自己编织
  • 我自己想不出办法,因此提出了这个问题。但是有这样的可能性会减少一些在多语言项目上工作的样板——即不需要单独的规则来处理 Makefiles 中的 R-markdown 文件。

标签: r r-markdown knitr executable shebang


【解决方案1】:

您可以将 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.

【讨论】:

  • 谢谢,我认为这是一个非常聪明的解决方案。
  • 一个细节,shebang应该是#!/usr/bin/env Rscript,而不是#!/usr/bin/env/Rscript
  • 很抱歉。我错过了这一点,因为我正在使用 Rscript 二进制文件的绝对路径进行测试。我已经纠正了这个错误。
【解决方案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
  • 因此,我建议在负责调用Rscript 的shebang 中使用“包装器”。
  • 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
    

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

【讨论】:

  • 感谢您的回答,这也是一个非常好的方法,但我决定采用另一个答案,因为它不依赖于维护一个包含渲染说明的单独文件。
猜你喜欢
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 2011-06-24
  • 2019-08-19
  • 2014-07-20
  • 2012-05-30
  • 1970-01-01
相关资源
最近更新 更多