gpt4 book ai didi

r - 如何在 knitr 子文档中隐藏和传递变量?

转载 作者:行者123 更新时间:2023-12-04 00:56:02 25 4
gpt4 key购买 nike

knitr用(在我的情况下)R和LaTEX的组合代码制作PDF。可以从子文档中组合出一份文档。

当我现在使用它时,该文档由全局变量组合而成,传入和传出每个子文档。这使得生成意大利面条代码变得容易。

有没有办法让 R 变量对子文档“本地化”?如何明确导出变量?

我可以在子文档的末尾清空每个局部变量,但我想知道是否有一些合理的正式机制可以放松子文档之间的代码耦合。

最佳答案

knitr评估公共(public)环境中的所有 block (由 knit_global() 返回)。这是设计使然;就像源文件中的所有代码都在同一个环境中运行一样,所有 block 都在一个公共(public)环境中执行。这同样适用于 child documents因为它们(原则上,不是技术上的)只是主文档的一部分,外化到另一个文件。

这并不一定会导致意大利面条式代码:没有什么能阻止用户使用函数和其他对象来组织 knitr 中的代码/数据。文件。但可能很少有用户这样做……

因此,对于 block /子文档没有封装机制的原因是它们应该共享一个公共(public)环境,因为它们是一个(主)文档的一部分。

但是,可以通过让用户控制对象子文档和主文档共享的方式包含子文档。解决方案基于函数knit_child()这与 chunk option 非常相似child .调用knit_child() 的优势直接(相对于通过 child 选项隐含)是设置 envir 的可能性。定义“代码块被评估的环境”的参数(来自 ?knit )。

左右knit_child() , 我写了包装 IsolatedChild为了简化问题:

IsolatedChild <- function(input, ...) {

evaluationEnv <- list2env(x = list(...), parent = as.environment(2))
cat(asis_output(knit_child(input = input, envir = evaluationEnv, quiet = TRUE)))
return(evaluationEnv)
}

传递给 ... 的参数将在子文档中可用。 (命名它们,参见下面的示例。)该函数返回评估子文档的环境。

指定 parentlist2env很关键,我选择了 as.environment(2)根据 this answer .否则 parent默认为 parent.frame() ,从而暴露 knit_global() 中的对象到子文档。
assign可用于制作从 IsolatedChild 返回的对象在全局环境中可用。

注意 cat(asis_output())周边 build knit_child这确保子文档的输出正确地包含在主文档中,而不管 results在当前 block 中设置。

在转向示例之前,最后要说两句:
  • 如果子文档和主文档不应该共享任何对象,则此方法过于复杂。只需knit子文档和使用\include{}将其包含在主文档中。
  • 这种方法可能会带来一些陷阱。特别是“孤立 child ”的封闭环境需要小心,因为搜索路径可能看起来与预期不同。请注意,主文档和子文档共享 knitr选项。此外,两个文档都可以通过副作用(options()par()、打开的设备……)进行交互。


  • 下面是一个完整的示例/演示:
  • block inputNormal没有什么特别的,它只是正常行为的示范。 inputHidden演示 IsolatedChild() 的使用,将两个变量传递给子文档。
  • IsolatedChild()返回这两个值以及在子级中创建的第三个对象。
  • check证明传递给/在“孤立子”中创建的对象不会污染全局环境。
  • import显示如何 assign可用于将对象从“孤立的 child ”“导入”到全局环境。


  • main.Rnw:


    \documentclass{article}
    \begin{document}

    <<setup>>=
    library(knitr)

    objInMain <- TRUE

    IsolatedChild <- function(input, ...) {

    evaluationEnv <- list2env(x = list(...), parent = as.environment(2))
    cat(asis_output(knit_child(input = input, envir = evaluationEnv, quiet = TRUE)))
    return(evaluationEnv)
    }

    @

    <<inputNormal, child="child_normal.Rnw">>=
    @

    <<inputHidden, results = "asis">>=

    returned <- IsolatedChild(input = "child_hidden.Rnw",
    passedValue = 42,
    otherPassedValue = 3.14)
    cat(sprintf("Returned from hidden child: \\texttt{%s}",
    paste(ls(returned), collapse = ", ")))
    @

    <<check, results = "asis">>=
    cat(sprintf("In global evaluation environment: \\texttt{%s}",
    paste(ls(), collapse = ", ")))
    @

    <<import, results = "asis">>=
    assign("objInChildHidden", returned$objInChildHidden)
    cat(sprintf("In global evaluation environment: \\texttt{%s}",
    paste(ls(), collapse = ", ")))
    @
    \end{document}

    child_normal.Rnw:


    <<inChildNormal>>=
    objInChildNormal <- TRUE # visible in main.Rnw (standard behaviour)
    @

    child_hidden.Rnw:


    Text in \texttt{child\_hidden.Rnw}.

    <<inChildHidden>>=
    objInChildHidden <- TRUE

    print(sprintf("In hidden child: %s",
    paste(ls(), collapse = ", ")))


    # Returns FALSE.
    # Would be TRUE if "parent" weren't specifiet in list2env().
    exists("objInMain", inherits = TRUE)
    @

    main.pdf:



    main.pdf

    关于r - 如何在 knitr 子文档中隐藏和传递变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34498734/

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