两栏排版中knitr/Sweave文档中的figure*环境

6

听起来应该是一个常见的问题,但我没有找到一个明显的技巧。 考虑下面的 knitr Rnw 文件:

\documentclass[twocolumn, 12pt]{article}
\usepackage{graphicx}
\begin{document}
%\SweaveOpts{dev=pdf, fig.align=center}
\begin{figure*}
<<aaa, fig.width=8, fig.height=5, fig.show=hold>>=
plot(1,1)
@
\end{figure*}
\end{document}

我希望这个宽度较大的图示跨越两栏来展示,使用{figure*}的LaTeX环境。有相应的钩子可以实现吗?
编辑:用figure*包裹代码块后,输出如下。

你可能会在http://tex.stackexchange.com/上更加幸运。 - Martin Schröder
@MartinSchröder 是的,同意。但我可能应该将其简化为latex问题,并且我不确定kframe环境最初是从哪里来的(从源代码来看,它似乎是私人通信)。 - baptiste
3个回答

8

两个事实:

  1. knitr 为您提供了一切,因此通常不需要使用 LaTeX 技巧;
  2. 有一个 chunk hook 可以用来包装您的块结果;

一个简单的解决方案是:

knit_hooks$set(chunk = function(x, options) {
                       sprintf('\\begin{figure*}\n%s\n\\end{figure*}', x)
})

我会把剩下的工作留给你处理更多细节方面的选项(例如,当options$fig.keep == 'none'时,您不应该将输出包装在figure*中)。您可能想看看LaTeX的默认chunk钩子是如何在knitr中定义的,以更好地了解chunk钩子的工作原理。

然而,在这种情况下,我倾向于在文档中自己编写LaTeX代码,而不是自动创建它。在获得figure*之后,您可以开始考虑\caption{}\label{}(并不难),但我仍然希望在LaTeX中看到它们。


听起来非常有前途,谢谢。然而,据我所知,这个钩子将应用于文档中的每个块,对吗?如果我只想让一个特定的块具有此行为,我应该定义一个新的可选钩子,比如fullwidth。我理解得对吗? - baptiste
是的,它适用于所有代码块。如果需要单独控制,您可以添加一个代码块选项,例如 fullwidth,然后在代码块钩子中使用 if (options$fullwidth) {use figure*...} else {normal output},代码块看起来像 <<..., fullwidth=TRUE>>= - Yihui Xie
我的第一次尝试确实是将代码块包装在\begin{figure*} \end{figure*}中,但由于某种原因,对齐方式出现了问题(请参见编辑部分)。 - baptiste
我不知道。现在看起来完全是LaTeX的问题。你需要做一些功课,比如为什么\centering{}figure*中不能正常工作。 - Yihui Xie
从latex输出来看,整个代码块都在{kframe}中,这会改变其位置。这是相当高级的TeX,显然是由framed LaTeX包的作者编写的。确实是一个TeX问题。 - baptiste

2

我不确定如何操作knitr,但对于Sweave(和基本的latex),实际上有一个技巧:让R代码生成一个pdf文件,然后使用标准的\includegraphics命令来引入它。

因此,可以按照以下步骤进行操作:

\documentclass[twocolumn, 12pt]{article}
\usepackage{graphicx}
\begin{document}
%\SweaveOpts{dev=pdf}

<<aaa,fig=FALSE,print=FALSE,echo=FALSE>>=
pdf("mychart.pdf", width=6, height=3)
set.seed(42)
plot(cumsum(rnorm(100)), type='l', main="yet another random walk")
invisible(dev.off())
@

\begin{figure*}
  \includegraphics{mychart.pdf}
\end{figure*}

\end{document}

我得到了下面的文档(然后将其从pdf转换为png):

在此输入图像描述


(注意:文档无法翻译,只能提供对文档的简单描述。)

来吧,你现在在英联邦。你已经离“优雅”很远了 :) 可能还有其他技巧。检查一下由Achim Zeileis作为(共同)作者的小品文总是一个好主意,因为他是LaTeX技巧的不竭源泉。 - Dirk Eddelbuettel
我承认我有点挑剔,但我相信存在一些更整洁的方法。如果我要使用这个技巧,我可能会让 brew 可靠地在 R 和 LaTeX 之间链接图形文件名。 - baptiste
我倾向于有一个子目录figures/,在其中编写并将Sweave块命名为生成的pdf相同的名称。这样做效果很好。此外,如果pdf存在,你可以免费获得缓存,因为你可以决定跳过重新创建它。 - Dirk Eddelbuettel
我对可重复研究的方法是让软件负责那些我自己无法可靠完成的事情。一致的命名方案就是其中之一。我恭敬地建议您尝试 knitr,它正在证明在缓存、pgf、Sweave 的技巧方面有所改变。 - baptiste
它在队列中,这是一种委婉的说法,意思是我有一堆其他事情要先处理。此外,我们在Sweave方面讨论的内容并不会削弱可重复研究方法的应用。 - Dirk Eddelbuettel

1
我在为IEEE两栏会议论文准备跨越两列的图形时遇到了类似的问题。
设置块钩子导致我的设置出现了一些奇怪的错误。 即使是这个简单的钩子:knit_hooks$set(chunk = function(x, options) x) 但是在查看knitr::opts_chunk$get()后,我意识到仅仅设置fig.env="figure*"就能优雅地解决问题。
以下是我的Rnw文件中块的外观:
<<fig1, fig.width=18, fig.height=6, fig.env="figure*">>=
@

问题和@Yihui的答案可以追溯到2012年,所以情况可能已经发生了变化。 - baptiste

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接