模块化的 R markdown 结构
Modularized R markdown structure
已经有一些关于此的问题,但它们要么不清楚,要么提供的解决方案不起作用,可能是因为它们已经过时了:
- How to source R Markdown file like `source('myfile.r')`?
- http://yihui.name/knitr/demo/externalization/
大型项目的模块化代码结构
R Markdown/Notebook 很好,但它的呈现方式通常是一个包含所有文本和所有代码块的文件。我经常有这样的单一文件结构不是一个好的设置的项目。相反,我使用单个 .R
主文件按顺序加载其他 .R
文件。我想使用 R Notebook 复制此结构,即我有一个 .Rmd
文件,我从多个 .R
文件中调用代码。
以这种方式处理项目的好处在于,它允许使用 .R
文件的 RStudio 进行良好的正常工作流程,而且还允许 R Notebook/Markdown 的整洁输出,而无需重复代码.
最小示例
这是为了使示例尽可能小而进行了简化。两个 .R
文件和一个主 .Rmd
文件。
start.R
# libs --------------------------------------------------------------------
library(pacman)
p_load(dplyr, ggplot2)
#normally load a lot of packages here
# data --------------------------------------------------------------------
d = iris
#use iris for example, but normally would load data from file
# data manipulation tasks -------------------------------------------------
#some code here to extract useful info from the data
setosa = dplyr::filter(d, Species == "setosa")
plot.R
#setosa only
ggplot(setosa, aes(Sepal.Length)) +
geom_density()
#all together
ggplot(d, aes(Sepal.Length, color = Species)) +
geom_density()
然后是笔记本文件:
notebook.Rmd
:
---
title: "R Notebook"
output:
html_document: default
html_notebook: default
---
First we load some packages and data and do slight transformation:
```{r start}
#a command here to load the code from start.R and display it
```
```{r plot}
#a command here to load the code from plot.R and display it
```
期望的输出
所需的输出是手动将 start.R
和 plot.R
中的代码复制到 notebook.Rmd
中的代码块中得到的输出。这看起来像这样(由于缺少屏幕 space 而缺少一些内容):
我尝试过的事情
source
这会加载代码,但不会显示它。它只显示 source
命令:
knitr::read_chunk
有人提到了这个命令 here,但据我所知,实际上它与 source
的作用相同:它加载代码但不显示任何内容。
如何获得所需的输出?
解决方案是使用 knitr 的块选项 code
。根据knitr docs:
code: (NULL; character) if provided, it will override the code in the
current chunk; this allows us to programmatically insert code into the
current chunk; e.g. a chunk option code =
capture.output(dump('fivenum', '')) will use the source code of the
function fivenum to replace the current chunk
但是没有提供示例。听起来好像必须给它一个字符向量,所以我们试试 readLines
:
```{r start, code=readLines("start.R")}
```
```{r plot, code=readLines("start.R")}
```
这会产生所需的输出,从而允许模块化项目结构。
直接给它提供一个文件是行不通的(即 code="start.R"
),但会是一个很好的改进。
为了与 R Notebooks 的互操作性,您可以使用 knitr 的 read_chunk
方法,如上所述。在笔记本中,你必须在设置块中调用 read_chunk
;由于您可以 运行 笔记本块以任何顺序,这确保了外部代码将始终可用。
这是一个使用 read_chunk
将代码从外部 R 脚本导入笔记本的最小示例:
example.Rmd
```{r setup}
knitr::read_chunk("example.R")
```
```{r chunk}
```
example.R
## ---- chunk
1 + 1
当您在笔记本中执行空块时,将插入外部文件中的代码,并内联显示结果,就好像该块包含该代码一样。
根据我上面的评论,我使用此处的库来处理文件夹中的项目:
```{ r setup, echo=FALSE, message=FALSE, warning=FALSE, results='asis'}
library(here)
insert <- function(filename){
readLines(here::here("massive_report_folder", filename))
}
```
然后每个块看起来像
```{ r setup, echo=FALSE, message=FALSE, warning=FALSE,
results='asis', code=insert("extra_file.R")}
```
已经有一些关于此的问题,但它们要么不清楚,要么提供的解决方案不起作用,可能是因为它们已经过时了:
- How to source R Markdown file like `source('myfile.r')`?
- http://yihui.name/knitr/demo/externalization/
大型项目的模块化代码结构
R Markdown/Notebook 很好,但它的呈现方式通常是一个包含所有文本和所有代码块的文件。我经常有这样的单一文件结构不是一个好的设置的项目。相反,我使用单个 .R
主文件按顺序加载其他 .R
文件。我想使用 R Notebook 复制此结构,即我有一个 .Rmd
文件,我从多个 .R
文件中调用代码。
以这种方式处理项目的好处在于,它允许使用 .R
文件的 RStudio 进行良好的正常工作流程,而且还允许 R Notebook/Markdown 的整洁输出,而无需重复代码.
最小示例
这是为了使示例尽可能小而进行了简化。两个 .R
文件和一个主 .Rmd
文件。
start.R
# libs --------------------------------------------------------------------
library(pacman)
p_load(dplyr, ggplot2)
#normally load a lot of packages here
# data --------------------------------------------------------------------
d = iris
#use iris for example, but normally would load data from file
# data manipulation tasks -------------------------------------------------
#some code here to extract useful info from the data
setosa = dplyr::filter(d, Species == "setosa")
plot.R
#setosa only
ggplot(setosa, aes(Sepal.Length)) +
geom_density()
#all together
ggplot(d, aes(Sepal.Length, color = Species)) +
geom_density()
然后是笔记本文件:
notebook.Rmd
:
---
title: "R Notebook"
output:
html_document: default
html_notebook: default
---
First we load some packages and data and do slight transformation:
```{r start}
#a command here to load the code from start.R and display it
```
```{r plot}
#a command here to load the code from plot.R and display it
```
期望的输出
所需的输出是手动将 start.R
和 plot.R
中的代码复制到 notebook.Rmd
中的代码块中得到的输出。这看起来像这样(由于缺少屏幕 space 而缺少一些内容):
我尝试过的事情
source
这会加载代码,但不会显示它。它只显示 source
命令:
knitr::read_chunk
有人提到了这个命令 here,但据我所知,实际上它与 source
的作用相同:它加载代码但不显示任何内容。
如何获得所需的输出?
解决方案是使用 knitr 的块选项 code
。根据knitr docs:
code: (NULL; character) if provided, it will override the code in the current chunk; this allows us to programmatically insert code into the current chunk; e.g. a chunk option code = capture.output(dump('fivenum', '')) will use the source code of the function fivenum to replace the current chunk
但是没有提供示例。听起来好像必须给它一个字符向量,所以我们试试 readLines
:
```{r start, code=readLines("start.R")}
```
```{r plot, code=readLines("start.R")}
```
这会产生所需的输出,从而允许模块化项目结构。
直接给它提供一个文件是行不通的(即 code="start.R"
),但会是一个很好的改进。
为了与 R Notebooks 的互操作性,您可以使用 knitr 的 read_chunk
方法,如上所述。在笔记本中,你必须在设置块中调用 read_chunk
;由于您可以 运行 笔记本块以任何顺序,这确保了外部代码将始终可用。
这是一个使用 read_chunk
将代码从外部 R 脚本导入笔记本的最小示例:
example.Rmd
```{r setup}
knitr::read_chunk("example.R")
```
```{r chunk}
```
example.R
## ---- chunk
1 + 1
当您在笔记本中执行空块时,将插入外部文件中的代码,并内联显示结果,就好像该块包含该代码一样。
根据我上面的评论,我使用此处的库来处理文件夹中的项目:
```{ r setup, echo=FALSE, message=FALSE, warning=FALSE, results='asis'}
library(here)
insert <- function(filename){
readLines(here::here("massive_report_folder", filename))
}
```
然后每个块看起来像
```{ r setup, echo=FALSE, message=FALSE, warning=FALSE,
results='asis', code=insert("extra_file.R")}
```