0

我正在寻求一种将 Rmd 文档(包含对各种“子”文件的引用)呈现到没有这些依赖关系的独立R Notebook 的方法。

目前,.Rmd 代码块位于许多 .R、.py 和 .sql 文件中,并在报告中使用

```{r extraction, include=FALSE, cache=FALSE}
knitr::read_chunk("myscript.R")
```

其次是

```{r chunk_from_myscript}
```

如此处所述

我这样做是为了避免代码重复并允许单独运行源文件,但是这些代码块只能通过调用knitrender(何时read_chunk运行并且代码块可用)在报告中执行。

有没有办法在只填充这些块的情况下分拆 Rmd(在编织之前)?

这个功能

rmarkdown::render("report.Rmd", clean = FALSE)

extraction几乎到达那里,因为它在删除和填充时留下了降价文件,chunk_from_myscript但是由于这些文件是直接降价文件,因此这些块不再可执行并且缺少块选项。它显然也不包括eval=TRUE, echo=FALSE运行生成的笔记本所需的块。

我也看过,knitr::spin但这意味着将报告的内容传播到每个源文件,并不是非常理想。

代表

报告.Rmd

---
title: 'Report'
---

```{r read_chunks, include=FALSE, cache=FALSE}
knitr::read_chunk("myscript.R")
```

Some documentation

```{r chunk_from_myscript}
```

Some more documentation

```{r chunk_two_from_myscript, eval=TRUE, echo=FALSE}
```

我的脚本

#' # MyScript
#' 
#' This is a valid R source file which is formatted
#' using the `knitr::spin` style comments and code
#' chunks.
#' The file's code can be used in large .Rmd reports by
#' extracting the various chunks using `knitr::read_chunk` or
#' it can be spun into its own small commented .Rmd report
#' using `knitr::spin`

# ---- chunk_from_myscript
sessionInfo()

#' This is the second chunk

# ---- chunk_two_from_myscript
1 + 1

期望的输出

笔记本.Rmd

---
title: 'Report'
---

Some documentation

```{r chunk_from_myscript}
sessionInfo()
```

Some more documentation

```{r chunk_two_from_myscript, eval=TRUE, echo=FALSE}
1 + 1
```
4

2 回答 2

1

通过您的工作,reprex我现在可以更好地了解您要解决的问题。您可以knit进入output.Rmd以将您的报告和脚本合并到一个降价文件中。

knitr::read_chunk我没有使用 ,而是knitr::spin将输出读catasis另一个.Rmd文件。另请注意,该params$final标志允许在设置为时呈现最终文档,或在默认情况下TRUE允许knit到中间文件。.RmdFALSE

报告.Rmd

---
title: "Report"
params:
  final: false
---

```{r load_chunk, include=FALSE}
chunk <- knitr::spin(text = readLines("myscript.R"), report = FALSE, knit = params$final)
```


Some documentation

```{r print_chunk, results='asis', echo=FALSE}
cat(chunk, sep = "\n")
```

生成中间文件:

rmarkdown::render("report.Rmd", "output.Rmd")

输出.Rmd

---
title: "Report"
---

Some documentation

```{r chunk_from_myscript, echo=TRUE}
sessionInfo() 
```

使用 second output.Rmd,您可以继续使用我在下面的原始响应进行渲染,html_notebook以便可以共享文档而无需重新生成但仍包含源 R 降价文件。

要呈现最终文档,report.Rmd您可以使用:

rmarkdown::render("report.Rmd", params = list(final = TRUE))

原始回复

您需要在render声明中包含其他参数。

rmarkdown::render(
  input = "output.Rmd",
  output_format = "html_notebook",
  output_file = "output.nb.html"
)

当您在RStudio.nb.html中打开文件时,嵌入的文件将在编辑窗格中可见。.Rmd

于 2017-12-20T02:42:43.000 回答
0

由于既不knitr::knit也不rmarkdown::render适合渲染R markdown,我已经设法通过将块文本动态插入每个空块并将其写入新文件来解决这个问题:

library(magrittr)
library(stringr)

# Find the line numbers of every empty code chunk
get_empty_chunk_line_nums <- function(file_text){
  # Create an Nx2 matrix where the rows correspond
  # to code chunks and the columns are start/end line nums
  mat <- file_text %>%
    grep(pattern = "^```") %>%
    matrix(ncol = 2, byrow = TRUE)
  # Return the chunk line numbers where the end line number
  # immediately follows the starting line (ie. chunk is empty)
  empty_chunks <- mat[,1] + 1 == mat[,2]
  mat[empty_chunks, 1]
}

# Substitute each empty code chunk with the code from `read_chunk`
replace_chunk_code <- function(this_chunk_num) {
  this_chunk <- file_text[this_chunk_num]
  # Extract the chunk alias
  chunk_name <- stringr::str_match(this_chunk, "^```\\{\\w+ (\\w+)")[2]
  # Replace the closing "```" with "<chunk code>\n```"
  chunk_code <- paste0(knitr:::knit_code$get(chunk_name), collapse = "\n")
  file_text[this_chunk_num + 1] %<>% {paste(chunk_code, ., sep = "\n")}
  file_text
}

render_to_rmd <- function(input_file, output_file, source_files) {
  lapply(source_files, knitr::read_chunk)
  file_text <- readLines(input_file)
  empty_chunks <- get_empty_chunk_line_nums(file_text)
  for (chunk_num in empty_chunks){
    file_text <- replace_chunk_code(file_text, chunk_num)
  }
  writeLines(file_text, output_file)
}

source_files <- c("myscript.R")
render_to_rmd("report.Rmd", "output.Rmd", source_files)

这具有保留块选项以及使用 Python 和 SQL 块的额外好处,因为在此步骤中不需要评估任何块。

于 2018-01-02T07:50:35.540 回答