当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在knitr子文档中隐藏和传递变量?》经验,为你挑选了1个好方法。

knitr使代码中的PDF成为(在我的情况下)R和LaTEX的组合.可以从子文档中组装文档.

正如我现在使用的那样,文档是由全局变量组合而成,传入和传出每个子文档.这样可以轻松生成意大利面条代码.

有没有办法让R变量成为子文档的"本地"?如何明确导出变量?

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



1> CL...:

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

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

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

但是,它可能包括在给出了对象子文档和主文档共享的用户控制的一种方式子文档.该解决方案基于knit_child()与块选项 非常相似的功能child.knit_child()直接调用(相对于通过child选项隐式调用)的优点是可以设置envir定义"要评估代码块的环境"的参数(from ?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)按照这个答案.否则parent将默认为parent.frame(),从而将对象暴露knit_global()给子文档.

assign可用于使IsolatedChild全局环境中可用的对象返回.

请注意,无论当前块中的设置如何,cat(asis_output())围绕knit_child该构造都可确保子文档的输出正确包含在主文档results中.

在转向示例之前,最后两个评论:

如果孩子和主文档不应该共享任何对象,这种方法过于复杂.只需knit将子文档用于\include{}将其包含在主文档中.

这种方法可能会带来一些陷阱.特别是"孤立的孩子"的封闭环境需要谨慎,因为搜索路径可能看起来与预期不同.请注意主文档和子文档共享knitr选项.此外,这两个文件可以通过副作用互动(options(),par(),打开设备...).


下面是一个完整的示例/演示:

inputNormal没有什么特别之处,它只是对正常行为的证明.inputHidden演示了如何使用IsolatedChild(),将两个变量传递给子文档.

IsolatedChild()返回这两个值以及子项中创建的第三个对象.

check 表明传递给"孤立子"的对象/创建的对象不会污染全局环境.

import展示了如何assign使用"导入"对象从"孤立子"到全局环境.


main.Rnw:

\documentclass{article}
\begin{document}

<>=
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)
}

@

<>=
@

<>=

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

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

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

child_normal.Rnw:

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

child_hidden.Rnw:

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

<>=
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


这太棒了,谢谢!我刚刚开始学习环境.它们似乎是传递东西的正确机制.
推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有