figure* environment in twocolumn knitr/Sweave document
Asked Answered
S

3

6

Sounds like it should be a common problem, but I didn't find an obvious trick. Consider the knitr Rnw file below,

\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}

I would like this wide figure to span two columns, using a {figure*} LaTeX environment. Is there a hook for that?

EDIT: wrapping the chunk in figure* gives the following output.

enter image description here

Shan answered 23/1, 2012 at 23:0 Comment(2)
You may have more luck at tex.stackexchange.comDeclinometer
@MartinSchröder yes, agreed. But I should probably strip it down to the latex problem, and I'm not sure where the kframe environment came from in the first place (from the source, it looks like a private communication).Shan
A
8

Two facts:

  1. knitr makes everything accessible for you, so LaTeX tricks are often unnecessary;
  2. there is a chunk hook with which you can wrap your chunk results;

A simple-minded solutions is:

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

I leave the rest of work to you to take care of more details in options (e.g. when options$fig.keep == 'none', you should not wrap the output in figure*). You may want to see how the default chunk hook for LaTeX is defined in knitr to know better how the chunk hook works.

However, in this case, I tend to write the LaTeX code by myself in the document instead of automatically creating it. After you have got figure*, you may start to think about \caption{} and \label{} (not hard, but I still want to see them in LaTeX).

Algebraic answered 24/1, 2012 at 2:26 Comment(5)
that sounds very promising, thanks. However, as I understand, this hook would apply to the each chunk in the document, right? If I want only one particular chunk to have this behavior, I should probably define a new optional hook, say fullwidth. Did I get this right?Shan
Yes it applies to all chunks. For individual control, you may add a chunk option like fullwidth, then use if (options$fullwidth) {use figure*...} else {normal output} in the chunk hook, and the chunk looks like <<..., fullwidth=TRUE>>=Algebraic
My first try was indeed to wrap the chunk in \begin{figure*} \end{figure*} but for some reason the alignment is broken (see edit).Shan
I do not know. It sounds like a completely LaTeX problem now. Do some homework like why \centering{} does not work in figure* for you.Algebraic
looking at the latex output, the whole chunk is in {kframe}, which alters the position. That's some pretty advanced TeX, apparently from the author of the framed LaTeX package. A TeX question indeed.Shan
M
2

Not sure about how knitr but for Sweave (and basic latex) there is in fact a trick: have the R code produce a pdf file, and then use standard \includegraphics to pull it in.

So with this:

\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}

I got the document below (which I then converted from pdf to png):

enter image description here

Minard answered 23/1, 2012 at 23:17 Comment(5)
C'mon, you're now in the Commonwealth. You left elegance way back home :) There may be other tricks. It is always a good idea to check vignette that have Achim Zeileis as a (co-)author as he is a never-ending source of latex tricks.Minard
admittedly I'm knitpicking, but I trust there exists some neater way. If I were to use this trick, I'd probably have brew reliably link the graphic filename between R and LaTeX.Shan
I tend to have a subdirectory figures/ to which I write, and name the Sweave chunk the same as the resulting pdf. Works well. Plus, you get caching for basically free b/c if the pdf exists, you may decide to skip recreating it.Minard
My approach to reproducible research is to have the software take care of things that I cannot trust myself to do reliably. A consistent naming scheme is one of them. I respectfully recommend that you try knitr, it's proving to be mind changing vis-à-vis (cache|pgf|)Sweave old tricks.Shan
It's in the queue, which is a polite way of saying that I have a metric ton of other things to get to first. Also, nothing we have discussed here w.r.t. Sweave takes away from reproducible research approaches.Minard
M
1

I also had a similar problem while preparing a figure that should span two columns in a IEEE two-column conference paper.

Setting the chunk hook caused some strange error in my setup. Even this simple hook: knit_hooks$set(chunk = function(x, options) x)

But after looking into knitr::opts_chunk$get(), I realized that simply setting fig.env="figure*" solves the problem in an elegant way.

Here is how my chunk looks like in an Rnw file:

<<fig1, fig.width=18, fig.height=6, fig.env="figure*">>=
@
Monotint answered 5/4, 2016 at 21:40 Comment(1)
the question and @Yihui 's answer date back 2012, so things may well have changedShan

© 2022 - 2024 — McMap. All rights reserved.