我有以下名为Rmd
的{{1}}文件:
test.Rmd
我想通过以下方式调用渲染:
---
title: "test"
output: html_document
---
```{r}
print(y)
```
```{r}
x <- "don't you ignore me!"
print(x)
```
但失败:
render('test.Rmd', output_format = "html_document",
output_file = 'test.html',
envir = list(y="hello"))
第一个块运行得很好,所以工作正常。如果我在全局环境中定义processing file: test.Rmd
|................ | 25%
ordinary text without R code
|................................ | 50%
label: unnamed-chunk-1
|................................................. | 75%
ordinary text without R code
|.................................................................| 100%
label: unnamed-chunk-2
Quitting from lines 11-13 (test.Rmd)
Error in print(x) : object 'x' not found
,则可以在不使用y
参数的情况下运行它,并且效果很好。
我发现envir
可能不喜欢列表,所以我们给它一个适当的环境:
render
但是更糟糕的是,找不到y_env <- as.environment(list(y="hello"))
ls(envir = y_env)
# [1] "y"
render('test.Rmd', output_format = "html_document",
output_file = 'test.html',
envir = y_env)
!
print
现在文档中提到使用功能processing file: test.Rmd
|................ | 25%
ordinary text without R code
|................................ | 50%
label: unnamed-chunk-1
Quitting from lines 7-8 (test.Rmd)
Error in eval(expr, envir, enclos) : could not find function "print"
,所以出于绝望,我尝试这样做:
new.env
现在可以使用了!
y_env <- new.env()
y_env$y <- "hello"
render('test.Rmd', output_format = "html_document",
output_file = 'test.html',
envir = y_env)
回顾一下,我对几件事感到困惑:
processing file: test.Rmd
|................ | 25%
ordinary text without R code
|................................ | 50%
label: unnamed-chunk-1
|................................................. | 75%
ordinary text without R code
|.................................................................| 100%
label: unnamed-chunk-2
output file: test.knit.md
"C:/Program Files/RStudio/bin/pandoc/pandoc" +RTS -K512m -RTS test.utf8.md --to html --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output test.html --smart --email-obfuscation none --self-contained --standalone --section-divs --template "**redacted**\RMARKD~1\rmd\h\DEFAUL~1.HTM" --no-highlight --variable highlightjs=1 --variable "theme:bootstrap" --include-in-header "**redacted**\AppData\Local\Temp\RtmpGm9aXz\rmarkdown-str3f6c5101cb3.html" --mathjax --variable "mathjax-url:https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
Output created: test.html
会识别列表(第一个块未失败),却忽略了块中的常规分配答案 0 :(得分:9)
您的前两个示例由于不同的原因而失败。要了解这两种失败,首先必须了解有关 knitr 和 rmarkdown 如何评估代码块的知识。
当您在文件上调用rmarkdown::render()
时,每个代码块最终都会通过调用evaluate::evaluate()
进行评估。就其评估行为和作用域规则而言,evaluate()
的行为几乎与基本R函数eval()
相似。
(evaluate::evaluate()
与eval()
的最大不同之处在于它如何处理每个求值表达式的输出。如?evaluate
中所述,除了求值作为第一个参数传递的表达式之外, ,它“捕获了重新创建输出所必需的所有信息,就好像您已将代码复制并粘贴到R终端中一样。”该信息包括图形以及警告和错误消息,这就是为什么在针织!)
无论如何,最终从函数evaluate()
中对knitr:::block_exec()
的调用看起来像这样
evaluate::evaluate(code, envir = env, ...)
其中:
code
是字符串的向量,给出构成当前块的(可能是多个)表达式。
env
是您在对envir
的原始调用中提供了rmarkdown::render()
形式参数的值。
在您的第一个示例中,envir
是一个列表,而不是环境。在这种情况下,评估是在函数调用创建的本地环境中进行的。首先在通过?eval
的列表中查找未解析的符号(在?evaluate
和envir
中都有记录),然后在{{1}给定的环境链中查找}参数。至关重要的是,分配是在临时评估环境中进行的,临时评估环境在函数调用完成后就不复存在了。
因为enclos
一次对表达式的字符向量进行操作,所以当evaluate()
是一个列表时,在其中一个表达式中创建的变量将无法在后续表达式中使用表达式。
当envir
的{{1}}参数是一个列表时,您的代码块最终将通过如下调用进行评估:
envir
效果与您用rmarkdown::render()
进行的效果完全相同:
library(evaluate)
code <- c('x <- "don\'t you ignore me!"',
'print(x)')
env <- list(y = 1:10)
evaluate(code, envir = env)
## Or, for prettier printing:
replay(evaluate(code, envir = env))
## > x <- "don't you ignore me!"
## > print(x)
## Error in print(x): object 'x' not found
当eval()
是env <- list(y =1 :10)
eval(quote(x <- "don't you ignore me"), envir = env)
eval(quote(x), envir = env)
## Error in eval(quote(x), envir = env) : object 'x' not found
返回的环境时,由于其他原因会出现错误。在这种情况下,您的代码块最终将通过如下调用进行评估:
envir=
您已经注意到,此操作失败是因为as.environment(list())
返回了一个环境,该环境的周围环境为空环境(即library(evaluate)
code <- c('x <- "don\'t you ignore me!"',
'print(x)')
env <- as.environment(list(y = 1:10))
evaluate(code, envir = env)
## Or, for prettier printing:
replay(evaluate(code, envir = env))
## > x <- "don't you ignore me!"
## Error in x <- "don't you ignore me!": could not find function "<-"
## > print(x)
## Error in print(x): could not find function "print"
返回的环境)。 as.environment()
(就像emptyenv()
一样)会在evaluate()
中寻找符号eval()
,当找不到符号<-
时,便启动了一系列封闭环境,此处,不包含任何匹配项。 (还请注意,当env
是环境而不是列表时,不使用envir
参数。)
要执行所需的操作,您需要创建一个环境,该环境:(1)包含列表中的所有对象以及该对象; (2)包含您对enclos
的调用的父环境(即通常评估对render()
的调用的环境)作为其封闭环境。最简洁的方法是使用漂亮的render()
函数,如下所示:
list2env()
这样做将导致您的代码块被如下所示的代码评估:
env <- list2env(list(y="hello"), parent.frame())
render('test.Rmd', output_format = "html_document",
output_file = 'test.html',
envir = env)