Skip to content

Computing plot size in Sweave

4 messages · BXC (Bendix Carstensen), Yihui Xie, Marc Schwartz

#
Sometimes you want to compute the physical size of a plot based on data.
In R itself this is no problem.

But is there a way to compute the values of height and width in S-weave, say:

<<graph,fig=TRUE,height=xx,width=yy>>=

where xx and yy are computed and not physically written in the document?

Bendix
______________________________________________

Bendix Carstensen 
Senior Statistician
Epidemiology

Steno Diabetes Center A/S
Niels Steensens Vej 2-4
DK-2820 Gentofte
Denmark
+45 44 43 87 38 (direct)
+45 30 75 87 38 (mobile)
bxc at steno.dk    http://BendixCarstensen.com
www.steno.dk

This e-mail (including any attachments) is intended for ...{{dropped:8}}
#
I guess that is not possible with Sweave, but it is possible in the
knitr package (an alternative to Sweave). You can set

opts_knit$set(eval.opts = c('fig.height', 'fig.width'))

so that these two options will be evaluated as R expressions (e.g.
fig.height=x means it takes value from a variable x).

Note width/height have been renamed to fig.width/fig.height in knitr.
See http://yihui.name/knitr/

Regards,
Yihui
--
Yihui Xie <xieyihui at gmail.com>
Phone: 515-294-2465 Web: http://yihui.name
Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA
On Mon, Feb 20, 2012 at 9:15 AM, BXC (Bendix Carstensen) <bxc at steno.dk> wrote:
#
On Feb 20, 2012, at 9:15 AM, BXC (Bendix Carstensen) wrote:

            
Bendix,

By default, Sweave.sty sets:

\setkeys{Gin}{width=0.8\textwidth}

which modifies the default \includegraphics LaTeX command auto-generated during Sweave processing. This means that irrespective of the 'height' and 'width' arguments in the figure chunk header, which do control the size of the PDF/EPS files created, the actual size of the graphic as included in the resultant document will ALWAYS be 80% of the current text width and the height will be scaled accordingly.

In general, if you wanted to control the actual height and width of the figure in the resultant document, you could set:

<<FigureChunkName,include=false,echo=false,fig=true,height=YourHeight,width=YourWidth>>=

Plot Code Here

@

\begin{figure}[tbp]
\centering
\includegraphics{RnwFileName-FigureChunkName}
\caption[LOF Caption]{Some Longer Caption}
\end{figure}

'RnwFileName' is the name of your working .Rnw Sweave file and 'FigureChunkName' is the name of the figure chunk and as a result, the graphic file name being created by Sweave, separated by the hyphen ('-').

By setting the 'include' option to false, Sweave does not auto-generate the \includegraphics line with the "width=0.8\textwidth" argument, and you then explicitly include it in the LaTeX code following the figure chunk. The plot file(s) would then be created with the height and width parameters in the figure chunk header and the resultant document will have a figure of the size you desire, overriding the default behavior.

In my .Rnw files, I actually set:

  \usepackage[nogin]{Sweave}

in my preamble, which overrides the default 'Gin' behavior. Then the height and width parameters in the figure chunks are reflected in the resultant document, but of course, I need to explicitly pre-define those.

If you want to calculate the figure's height and width at run-time, I suspect that the only way to do that would be to have your R code generate all of the LaTeX code output at runtime as well. So something like the following:

<<CodeChunkName,echo=false>>=

# Plot Size Calculations Here
Height <- ResultOfCalcs
Width <- ResultOfCalcs

pdf("MyPlotFileName.pdf", height = Height, width = Width)

Plot Code Here

dev.off()

cat("\\begin{figure}[tbp]\n")
cat("\\centering\n")
cat("\\includegraphics{MyPlotFileName}\n") 
cat("\\caption[LOF Caption]{Some Longer Caption}\n")
cat("\\end{figure}\n")

@


The result of the cat() function calls will be to output the included character vectors to the .tex file being created by Sweave at run-time. So you are using R in a normal code chunk to generate LaTeX code.

If you need an EPS file either in place of the PDF (because you are using postscript stuff like pstricks) or in addition to the PDF, you can replace the pdf() call with postscript() or run a second iteration of the plotting code using postscript()/dev.off() as well.

HTH,

Marc Schwartz
#
Yes, with the old good cat() and results=tex, you can do anything. It
is just so unnatural. Why must a simple task like setting the size of
a plot involve with so much coding work?

% complete knitr code
<<setup, include=FALSE>>=
opts_knit$set(eval.opts = c('fig.height', 'fig.width'))
my.height = 6; my.width = 7
@

<<use-my-size, fig.height=my.height, fig.height=my.height,
out.width=.8\textwidth>>=
plot(rnorm(100))
@

No cats are involved here. Besides, cat() is hard-coded; you have to
remember to change the filename when your label is changed, and I do
not mind writing pdf()/dev.off() once, but what if I have a hundred
plots in the document -- five hundred cats jumping around? And you
also want to hide them in the backyard so the readers won't see them.

Regards,
Yihui
--
Yihui Xie <xieyihui at gmail.com>
Phone: 515-294-2465 Web: http://yihui.name
Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA
On Mon, Feb 20, 2012 at 3:34 PM, Marc Schwartz <marc_schwartz at me.com> wrote: