r语言 - Knitr语言 - 格式化块输出和创建新的块选项的良好实践



在问任何事情之前,我想为几件事道歉:首先,我承认我对社区的贡献不大。我从不回答问题,也很少问一些问题,因为我首先挖掘所有内容 - 这意味着,当我这样做时,就是问一些长而漂亮的问题。其次,我的问题实际上是两个不太相关的问题,我认为这不是一个好的做法(我第一次发布任何东西)。如果你想让我把它们分开,让我知道,它会完成的。

因此,解决问题:

我目前正在编写一个需要显示表格的报告。

在过去的几个月的工作中,我先后选择了几种方法来做到这一点,我最终得出的结论是,没有简单灵活的方法来显示原始代码和格式化的块输出,而不显示 R 代码格式化所述块代码的评估(此代码不是通用的;它唯一取决于显示的变量)- 实际上知道, 请参阅编辑

让我解释一下:我有一个简单的数据帧。我想显示定义 data.frame 的代码和对应于 data.frame 的 latex 表,而不显示生成乳胶代码的代码(例如,Hmisclatex函数或具有相应选项的xtable)。原因是它无关紧要,分散注意力,有时比有趣的代码更大。 我从来没有遇到过令人满意的方法,所以我想知道你们是如何做到的。目前,我想出的最佳工作解决方案是这个:

<<data>>=
mytable<-data.frame(a=c(1,2),b=c(2,3))
@
<<data.display,results='asis',echo=FALSE,dependson=data>>=
latex(mytable,caption="title",file="",<other options...>)
@

考虑到我之前的尝试,这是非常令人满意的,但是定义和显示变量mytable的需求让我很恼火。这个,以及我必须使用另一个块来做到这一点的事实。

我想过为 echo 选项使用数字向量,但它不能很好地与 tidy=FALSE 结合,并且根本不灵活(对代码的任何修改也可能导致需要修改选项值)。

我还考虑过仅使用和显示latexxtable函数(参数数量最少),并使用适当的 LaTeX 代码包装块以设置表环境,但我仍然需要一些来自latexxtable的选项,我必须引用块才能在此环境之外显示它(否则会产生错误)。

所以我的第一个问题是:您通常如何呈现生成要显示的表的代码?隐藏不需要的代码的方法是什么?在这个问题上,什么被认为是社区的良好做法?

最后,我现在正在研究的最后一个解决方案似乎是最有希望的,但它在技术上非常困难(至少对我来说),所以这就带来了我的第二个问题:

如何导航表达式树以恢复已放入控制台的参数之一?

这个想法是创建一个选项,该选项将影响重新定义的源钩子,该钩子将采用latex函数的第一个参数并显示它而不是完整的代码。

例如,代码

<<data,results='asis',latex=TRUE>>=
latex(
data.frame(a=c(1,2),b=c(2,3)),
caption="title",file="",
<other options...>)
@

。将在文档中显示为:

data.frame(a=c(1,2),b=c(2,3))

我想出了这个:

opts_chunk$set(latex=FALSE)
default.source<-knit_hooks$get("source")
knit_hooks$set(
source=function(x,options){
if(options$latex){
default.source(TODO(x),options) 
} else {
default.source(x,options)   
}
}
)

不多...substitute函数似乎毫无用处,因为它总是返回我"src"(我并不感到惊讶,它首先看到它)。 我希望我能采用整个函数并只提取第一个参数。(小编辑:我通过引用然后解析表达式成功地做到了这一点;不幸的是,换行符在此过程中丢失了。我试图改进它,但改变了重点 - 请参阅编辑)

我真的不想用这些函数和参数分散读者的注意力。你的方法是什么?你怎么看我的,你有什么想法让它发挥作用?提前感谢您的分享!

编辑:找到了一种方法!这个想法是使用名为code的新块选项 .定义新的输出钩子时,options$code 以字符串的形式存储代码。只需要在其上调用 latex 函数并捕获输出以将其用作新的块输出。这就是我实现它的方式(对不起,如果它不是最佳实践;请随时纠正它):

opts_chunk$set(latex=FALSE)
opts_template$set(latex=(list(results='asis',latex=TRUE)))
default.output<-knit_hooks$get("output")
knit_hooks$set(
output=function(x,options){
if(isTRUE(options$latex)){
if(class(options$latex.args)=="list"){
args<-options$latex.args
}
else {
args<-NULL
}
default.output(
paste0(
capture.output(
do.call("latex",
append(list(object=eval(parse(text=options$code)),file=""),args)
))
)[-1]
,collapse="")
,options)
} else {
default.output(x,options)
}
}
)

现在,这个块给了我我想要的:

<<data,opts.label="latex",latex.args=list(caption="title")>>=
data.frame(a=c(1,2),b=c(2,3))
@

code选项目前仅在 knitr 的开发版本中可用。 根据Yihui的github中的NEWS文件,这将是下一个稳定版本中的一项功能。

echo选项接受允许您指定要显示的行号的数字。

<<data, results = 'asis',echo = 1>>=
mytable<-data.frame(a=c(1,2),b=c(2,3))
latex(mytable,caption="title",file="",<other options...>)
@

唯一需要注意的是,行号不是基于物理行数,而是基于完整的表达式。因此,例如,以下代码仍将计为一行代码。

mytable <- data.frame(
a = c(1, 2),
b = c(2, 3)
)

由于 knitr 1.6 即将推出的功能("代码"选项),我已经能够解决这个问题。 我已经相应地编辑了第一篇文章。

最新更新