gpt4 book ai didi

r - 在受限环境中使用 `rmarkdown::render`

转载 作者:行者123 更新时间:2023-12-04 01:05:02 26 4
gpt4 key购买 nike

我有以下 Rmd我调用的文件 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

第一个 block 很好,所以有些东西起作用了。如果我定义 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

所以我对几件事感到困惑,回顾一下:
  • 为什么render识别列表(第一个 block 没有失败),然后忽略 block 中的常规分配
  • 为什么我的第二次尝试不起作用,它与我的第三次尝试有何不同?
  • 这是一个错误吗?
  • 这样做的惯用方法是什么?
  • 最佳答案

    您的前两个示例因不同原因而失败。要了解这两种故障,首先要了解 如何评估代码块。针织 Markdown .

    knitr 的通用代码块评估程序

    当您调用 rmarkdown::render()在您的文件中,每个代码块最终通过调用 evaluate::evaluate() 进行评估.就其评估行为和范围规则而言,evaluate()行为几乎与基本 R 函数 eval() 完全相同.

    (evaluate::evaluate()eval() 的最大区别在于它如何处理每个评估表达式的输出。如 ?evaluate 中所述,除了评估作为其第一个参数传递的表达式之外,它“捕获所有必要的信息重新创建输出,就像您已将代码复制并粘贴到 R 终端中一样”。该信息包括绘图、警告和错误消息,这就是为什么它在像 knitr 之类的包中如此方便的原因!)

    无论如何,最终调用 evaluate() ,来自函数knitr:::block_exec() ,看起来像这样

    evaluate::evaluate(code, envir = env, ...)

    其中:
  • code是一个字符串向量,给出了构成当前 block 的(可能是多个)表达式。
  • env是您提供的值 envir您对 rmarkdown::render() 的原始调用中的正式参数.


  • 你的第一个例子

    在您的第一个示例中, envir是一个列表,而不是一个环境。在这种情况下,评估是在函数调用创建的本地环境中执行的。未解析的符号(如 ?eval?evaluate 中所述)在通过 envir 的列表中首先查找然后在从 enclos 给出的环境链开始争论。至关重要的是,分配对于临时评估环境来说是本地的,一旦函数调用完成,它就会不存在。

    因为 evaluate()envir 时,一次对表达式的字符向量进行操作是一个列表,在其中一个表达式中创建的变量将不可用于后续表达式。

    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 是环境而不是列表时,不使用 enclos 参数。)

    推荐解决方案

    为了做你想做的事,你需要创建一个环境:(1)包含列表中的所有对象; (2) 将调用 render() 的父环境作为其封闭环境(即通常评估对 render() 的调用的环境)。最简洁的方法是使用漂亮的 list2env()函数,像这样:
    env <- list2env(list(y="hello"), parent.frame())
    render('test.Rmd', output_format = "html_document",
    output_file = 'test.html',
    envir = env)

    这样做会导致您的代码块被如下代码评估,这就是您想要的:
    library(evaluate)
    code <- c('x <- "don\'t you ignore me!"',
    'print(x)')
    env <- list2env(list(y = 1:10), envir = parent.frame())
    evaluate(code, envir = env)
    replay(evaluate(code, envir = env))
    ## > x <- "don't you ignore me!"
    ## > print(x)
    ## [1] "don't you ignore me!"

    关于r - 在受限环境中使用 `rmarkdown::render`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52724682/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com