【问题标题】:RMarkdown render to Notebook with child chunks includedRMarkdown 渲染到包含子块的笔记本
【发布时间】:2017-12-20 02:35:19
【问题描述】:

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

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

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

紧随其后

```{r chunk_from_myscript}
```

如文档所述here

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

有没有办法将 Rmd(在编织之前)与 只填充了这些块?

这个函数

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

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

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

代表

report.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.R

#' # 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

期望的输出

notebook.Rmd

---
title: 'Report'
---

Some documentation

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

Some more documentation

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

【问题讨论】:

    标签: r knitr r-markdown knitr-spin


    【解决方案1】:

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

    我没有使用knitr::read_chunk,而是使用knitr::spincatasis 输出读入另一个.Rmd 文件。还要注意params$final 标志,以允许在设置为TRUE 时呈现最终文档,或者默认允许knit 到中间.RmdFALSE

    report.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() 
    ```
    

    使用第二个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 将在编辑窗格中可见。

    【讨论】:

    • 有趣的是,嵌入文件仍然是旧的“未填充”.Rmd,但 .nb.html 显示了完全编译和填充的代码。
    • @ruaridhw,如果这对您没有帮助,请提供reprex。您在关于不编织但包含子文档信息的问题中存在相互矛盾的陈述。
    • 抱歉,添加了reprex。子文档是源文件,但看起来这些文件似乎无法与编织过程分开。您示例的输出是笔记本 html,但嵌入的 .Rmd 仍然是旧的 report.Rmd
    • @ruaridhw,现已编辑以解决两步最终渲染
    • 感谢您对此提供的广泛帮助。我无法使用代码rmarkdown::render("report.Rmd", output_file = "output.Rmd") 重现您的 output.Rmd 文件,因为默认输出是 HTML。你的意思是打电话给knitr::knit 吗?
    【解决方案2】:

    由于 knitr::knitrmarkdown::render 似乎都不适合渲染 to R 降价,我设法通过将块文本动态插入每个空块并将其写入一个新文件:

    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 块,因为不需要评估 此步骤中的任何块。

    【讨论】:

      猜你喜欢
      • 2021-06-13
      • 1970-01-01
      • 2023-04-03
      • 2019-03-27
      • 1970-01-01
      • 1970-01-01
      • 2019-12-30
      • 2019-07-28
      • 2018-10-27
      相关资源
      最近更新 更多