knitr使代码中的PDF成为(在我的情况下)R和LaTEX的组合.可以从子文档中组装文档.
正如我现在使用的那样,文档是由全局变量组合而成,传入和传出每个子文档.这样可以轻松生成意大利面条代码.
有没有办法让R变量成为子文档的"本地"?如何明确导出变量?
我可以在子doc的末尾将每个局部变量都清空,但我想知道是否有一些合理的正式机制来放松子文档之间的代码耦合.
CL.*_*CL. 14
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)
}
Run Code Online (Sandbox Code Playgroud)
传递给的参数...将在子文档中提供.(将它们命名,请参见下面的示例.)该函数返回已评估子文档的环境.
指定parent中list2env是至关重要的,我选择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}
<<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}
Run Code Online (Sandbox Code Playgroud)
child_normal.Rnw:
<<inChildNormal>>=
objInChildNormal <- TRUE # visible in main.Rnw (standard behaviour)
@
Run Code Online (Sandbox Code Playgroud)
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)
@
Run Code Online (Sandbox Code Playgroud)
main.pdf:
| 归档时间: |
|
| 查看次数: |
1558 次 |
| 最近记录: |