在 R markdown 中外部化配置文件和函数
Externalise config file and functions in R markdown
我无法理解在 R 笔记本中外部化代码的不同方法之间的(实际)差异。参考了之前的 questions or to the documentation,仍然不清楚采购外部 .R
文件或 read_chunk()
它们的区别。出于实际目的,让我们考虑以下内容:
我想用外部 config.R
文件加载库:根据我的说法,最直观的方法似乎是将 config.R
创建为
library(first_package)
library(second_package)
...
并且,在一般的 R 笔记本中(例如,main.Rmd
)称它为
```{r}
source('config.R')
```
```{r}
# use the libraries included above
```
然而,这并不能识别包含的包,所以看起来寻找外部配置文件是没有用的。同样使用 read_chunk()
代替。因此问题是:如何在顶部包含库,以便在主降价脚本中识别它们?
假设我想在外部定义全局函数,然后将它们包含在主笔记本中:按照与上面相同的方式将它们包含在外部 foo.R
文件中并包含它们在主要的。
同样,在这种情况下,似乎 read_chunk()
没有完成这项工作,而 source('foo.R')
可以;文档指出前者 "only evaluates code, but does not execute it": when is it ever 人们只想评估代码但不执行代码的情况?不同的姿势:为什么人们会出于实际目的使用 read_chunk()
而不是 source
?
This does not recognise the packages included
在您的示例中,first_package
和 second_package
在第二个代码块的工作环境中都可用。
尝试将 library(nycflights13)
放在 R 文件中,将 head(airlines)
放在 Rmd 文件的第二个块中。如果 nycflights13
包未成功加载 source
,则调用 knit("main.Rmd")
将失败。
read_chunk
实际上确实做到了这一点(与 source
一起)但是他们以不同的方式进行。使用 source
您将在 source
之后直接使用全局函数(如您所见)。但是,对于 read_chunk
,正如您所指出的,因为它 仅评估代码,但不执行它 您需要显式执行该块,然后该函数才可用。 (请参阅下面我使用 third_config_chunk
的示例。在报告中包含 third_config_chunk
的空块允许在后续块中调用全局 some_function
。)
关于“仅评估代码,但不执行它”,这是一个完整的 属性 R 编程,称为 lazy evaluation。这个想法是您可能想要创建一些函数或模板代码,这些函数或模板代码会被读入您的 R 环境但不会在现场执行,从而允许您在评估之前修改 environment/parameters。这也允许您多次执行相同的代码块,而 source
只会 运行 一次已经提供的代码。
考虑一个示例,其中您有一个外部 R 脚本,其中包含报告中不需要的大量设置代码。可以将此文件格式化为许多 "chunks",这些 "chunks" 将使用 read_chunk
加载到工作环境中,但在明确告知之前不会被评估。
为了使用 read_chunk()
外部化您的 config.R
,您可以将 R 脚本编写为:
config.R
# ---- config_preamble
## setup code that is required for config.R
## to run but not for main.Rmd
# ---- first_config_chunk
library(nycflights13)
library(MASS)
# ---- second_config_chunk
y <- 1
# ---- third_config_chunk
some_function <- function(x) {
x + y
}
# ---- fourth_config_chunk
some_function(10)
# ---- config_output
## code that is output during `source`
## and not wanted in main.Rmd
print(some_function(10))
要将此脚本与外部化方法一起使用,您需要按如下方式设置 main.Rmd:
main.Rmd
```{r, include=FALSE}
knitr::read_chunk('config.R')
```
```{r first_config_chunk}
```
The packages are now loaded.
```{r third_config_chunk}
```
`some_function` is now available.
```{r new_chunk}
y <- 20
```
```{r fourth_config_chunk}
```
## [1] 30
```{r new_chunk_two}
y <- 100
lapply(seq(3), some_function)
```
## [[1]]
## [1] 101
##
## [[2]]
## [1] 102
##
## [[3]]
## [1] 103
```{r source_file_instead}
source("config.R")
```
## [1] 11
如您所见,如果您要 source
这个文件,将无法在执行前修改对 some_function
的调用,并且该调用将打印输出“11 ”。现在这些块在环境中可用,它们可以被重新调用任意次数(例如,在更改 y
的值之后)或在当前环境中以任何其他方式使用(例如 new_chunk_two
) 如果您不希望 R 脚本的其余部分执行 .
,则 source
无法实现
我无法理解在 R 笔记本中外部化代码的不同方法之间的(实际)差异。参考了之前的 questions or to the documentation,仍然不清楚采购外部 .R
文件或 read_chunk()
它们的区别。出于实际目的,让我们考虑以下内容:
我想用外部
config.R
文件加载库:根据我的说法,最直观的方法似乎是将config.R
创建为library(first_package) library(second_package) ...
并且,在一般的 R 笔记本中(例如,
main.Rmd
)称它为```{r} source('config.R') ``` ```{r} # use the libraries included above ```
然而,这并不能识别包含的包,所以看起来寻找外部配置文件是没有用的。同样使用
read_chunk()
代替。因此问题是:如何在顶部包含库,以便在主降价脚本中识别它们?假设我想在外部定义全局函数,然后将它们包含在主笔记本中:按照与上面相同的方式将它们包含在外部
foo.R
文件中并包含它们在主要的。
同样,在这种情况下,似乎 read_chunk()
没有完成这项工作,而 source('foo.R')
可以;文档指出前者 "only evaluates code, but does not execute it": when is it ever 人们只想评估代码但不执行代码的情况?不同的姿势:为什么人们会出于实际目的使用 read_chunk()
而不是 source
?
This does not recognise the packages included
在您的示例中,
first_package
和second_package
在第二个代码块的工作环境中都可用。尝试将
library(nycflights13)
放在 R 文件中,将head(airlines)
放在 Rmd 文件的第二个块中。如果nycflights13
包未成功加载source
,则调用knit("main.Rmd")
将失败。read_chunk
实际上确实做到了这一点(与source
一起)但是他们以不同的方式进行。使用source
您将在source
之后直接使用全局函数(如您所见)。但是,对于read_chunk
,正如您所指出的,因为它 仅评估代码,但不执行它 您需要显式执行该块,然后该函数才可用。 (请参阅下面我使用third_config_chunk
的示例。在报告中包含third_config_chunk
的空块允许在后续块中调用全局some_function
。)
关于“仅评估代码,但不执行它”,这是一个完整的 属性 R 编程,称为 lazy evaluation。这个想法是您可能想要创建一些函数或模板代码,这些函数或模板代码会被读入您的 R 环境但不会在现场执行,从而允许您在评估之前修改 environment/parameters。这也允许您多次执行相同的代码块,而 source
只会 运行 一次已经提供的代码。
考虑一个示例,其中您有一个外部 R 脚本,其中包含报告中不需要的大量设置代码。可以将此文件格式化为许多 "chunks",这些 "chunks" 将使用 read_chunk
加载到工作环境中,但在明确告知之前不会被评估。
为了使用 read_chunk()
外部化您的 config.R
,您可以将 R 脚本编写为:
config.R
# ---- config_preamble
## setup code that is required for config.R
## to run but not for main.Rmd
# ---- first_config_chunk
library(nycflights13)
library(MASS)
# ---- second_config_chunk
y <- 1
# ---- third_config_chunk
some_function <- function(x) {
x + y
}
# ---- fourth_config_chunk
some_function(10)
# ---- config_output
## code that is output during `source`
## and not wanted in main.Rmd
print(some_function(10))
要将此脚本与外部化方法一起使用,您需要按如下方式设置 main.Rmd:
main.Rmd
```{r, include=FALSE}
knitr::read_chunk('config.R')
```
```{r first_config_chunk}
```
The packages are now loaded.
```{r third_config_chunk}
```
`some_function` is now available.
```{r new_chunk}
y <- 20
```
```{r fourth_config_chunk}
```
## [1] 30
```{r new_chunk_two}
y <- 100
lapply(seq(3), some_function)
```
## [[1]]
## [1] 101
##
## [[2]]
## [1] 102
##
## [[3]]
## [1] 103
```{r source_file_instead}
source("config.R")
```
## [1] 11
如您所见,如果您要 source
这个文件,将无法在执行前修改对 some_function
的调用,并且该调用将打印输出“11 ”。现在这些块在环境中可用,它们可以被重新调用任意次数(例如,在更改 y
的值之后)或在当前环境中以任何其他方式使用(例如 new_chunk_two
) 如果您不希望 R 脚本的其余部分执行 .
source
无法实现