是否有用于模块化报告生成的 \SweaveInput{} 的 R 降价模拟?

Is there a R markdown analog of \SweaveInput{} for modular report generation?

我非常喜欢 Sweave 中的一个功能是可以选择拥有单独的 Sweave 文件的 \SweaveInput{} 以获得更多 "modular" 报告,并且能够注释掉报告中的部分我不想使用单个 #\SweaveInput{part_x} 生成,而不必在整个代码块中添加或注释掉。 最近我决定转向 R Markdown 有多种原因,主要是实用性、报告中的交互式(闪亮)集成选项以及我真的不需要 LaTeX 的大量格式设置选项。 我发现从技术上讲,pandoc 能够通过将多个 Rmd 文件连接成一个 html 输出,但是如果可以从 "master" Rmd 文件中调用此行为,那就太好了。

任何答案,即使只是 "go back to Sweave, it is not possible in Markdown"。

,我们将不胜感激

我正在为 Windows 和 Linux 以及 Rstudio 0.98.1056 和 Rstudio 服务器 0.98.983 使用 R 3.1.1。

在主文档中使用类似这样的内容:

```{r child="CapsuleRInit.Rmd"}
```
```{r child="CapsuleTitle.Rmd", eval=TRUE}
```
```{r child="CapsuleBaseline.Rmd", eval=TRUE}
```

使用eval=FALSE跳过一个child。

对于RStudio用户:你可以定义一个主文档用于latex输出,但这对RMD文档不起作用,所以你总是要切换到主文档进行处理。请支持我对 RStudio 的功能请求;我已经尝试了两次,但在我看来,使用 child 文档的人太少,无法将其置于优先级列表中。

我不太理解上面答案中的一些术语,但解决方案涉及在 YAML header 中定义自定义 knit: hook。对于多部分文档,这允许您,例如:

  • 有一个 'main' 或 'root' Rmarkdown 文件和 output: markdown_document YAML header
  • 在调用 render 之前从 Rmd ⇒ md 渲染所有 child 文档,如果是 time-limiting
  • 则不渲染
  • 将多个文件(使用 child 代码块选项)合并为一个文件(例如报告中的章节)
  • write output: html_document (or other format) YAML headers for this compilation output on the fly, prepending to the markdown effectively write a fresh Rmarkdown file
    • ...然后呈现此 Rmarkdown 以获得输出,如果需要,删除过程中的中间文件

以上所有的代码 (dumped here) is described here, a post I wrote after working out the usage of custom knit: YAML header hooks recently (here)。

上例中的自定义 knit: 函数(即 rmarkdown::render 的替换)是:

(function(inputFile, encoding) {
  input.dir <- normalizePath(dirname(inputFile))
  rmarkdown::render(input = inputFile, encoding = encoding, quiet=TRUE,
                    output_file = paste0(input.dir,'/Workbook-tmp.Rmd'))
  sink("Workbook-compiled.Rmd")
    cat(readLines(headerConn <- file("Workbook-header.yaml")), sep="\n")
    close(headerConn)
    cat(readLines(rmdConn <- file("Workbook-tmp.Rmd")), sep="\n")
    close(rmdConn)
  sink()

  rmarkdown::render(input = paste0(input.dir,'/Workbook-compiled.Rmd'),
                  encoding = encoding, output_file = paste0(input.dir,'/../Workbook.html'))
  unlink(paste0(input.dir,'/Workbook-tmp.Rmd'))
})

...但都挤在了1行!

'master'/'root'/'control' 文件的其余部分或任何您想调用的文件负责为最终 HTML 输出编写上述 YAML通过一个中间 Rmarkdown 文件,它的第二个代码块通过调用 list.files()

以编程方式附加 child 文档
```{r include=FALSE}
header.input.file <- "Workbook-header.yaml"
header.input.dir <- normalizePath(dirname(header.input.file))
fileConn <- file(header.input.file)
writeLines(c(
  "---",
  paste0('title: "', rmarkdown::metadata$title,'"'),
  "output:",
  "  html_document:",
  "    toc: true",
  "    toc_depth: 3 # defaults to 3 anyway, but just for ease of modification",
  "    number_sections: TRUE",
  paste0("    css: ",paste0(header.input.dir,'/../resources/workbook_style.css')),
  '    pandoc_args: ["--number-offset=1", "--atx-headers"]',
  "---", sep="\n"),
  fileConn)
close(fileConn)
```

```{r child = list.files(pattern = 'Notes-.*?\.md')}
# Use file names with strict numeric ordering, e.g. Notes-001-Feb1.md
```

目录结构将包含一个 top-level 文件夹

  1. 最终输出Workbook.html
  2. 一个包含 workbook_style.css
  3. resources 子文件夹
  4. 一个 documents 子文件夹,其中包含所述主文件 "Workbook.Rmd" 以及名为 "Notes-001.Rmd"、"Notes-002.Rmd" 等的文件(以确保 list.files(pattern = "Notes-.*?\.Rmd) 上的文件匹配找到从而在呈现主 Workbook.Rmd 文件时使它们 children 以正确的顺序)

为了获得正确的文件编号,每个组成 "Notes-XXX.Rmd" 文件应包含以下样式的 YAML header:

---
title: "March: Doing x, y, and z"
knit: (function(inputFile, encoding) { input.dir <- normalizePath(dirname(inputFile)); rmarkdown::render(input = inputFile, encoding = encoding, quiet=TRUE)})
output:
  md_document:
    variant: markdown_github
    pandoc_args: "--atx-headers"
---

```{r echo=FALSE, results='asis', comment=''}
cat("##", rmarkdown::metadata$title)
```

Rmarkdown 文档顶部的代码块在评估时将 YAML 标题作为 second-level header 输入。 results='asis' 表示 return 普通 text-string 而不是

[1] "A text string"

您可以在 编织主文件之前编织这些文件中的每一个 - 删除呈现所有 child 文档并仅附加其 [=108= 的要求更容易] 降价输出。

我已经在上面的链接中描述了所有这些,但我认为不留下我的答案的实际代码是不礼貌的。

我不知道 RStudio 功能请求网站的效率如何...就我个人而言,我发现查看这些功能的源代码并不困难,谢天谢地是 open source,并且如果确实存在 不存在 而不是未记录的 inner-workings-informed 功能请求,则其软件开发人员可能更容易采取行动。

我对 Sweave 不熟悉,以上是你的目标吗?如果我理解正确的话,您只想以模块化方式控制文档的包含。 child = list.files() 语句可以解决这个问题:如果不通过文件通配,您可以 straight-up 将文件列为 child = c("file1.md","file2md")... 并切换该语句以更改 children。您还可以使用 YAML 控制 TRUE/FALSE 开关,因此自定义 header 的存在将设置一些 children 被包含,例如

potentially.absent.variable: TRUE

...在文档上方有一个无声的 include=FALSE 隐藏了第一个块的阴谋:

```{r include=FALSE}
!all(!as.logical(rmarkdown::metadata$potentially.absent.variable)
# ==> FALSE if potentially.absent.variable is absent
# ==> FALSE if anything other than TRUE
# ==> TRUE if TRUE

checkFor <- function(var) {
  return !all(!as.logical(rmarkdown::metadata[[var]])
}
```

```{r child = "Optional_file.md", eval = checkFor(potentially.absent.variable)}
```