cameronbracken / pgfSweave

Quality graphics and speedy compilation with Sweave
http://r-forge.r-project.org/projects/pgfsweave/
29 stars 6 forks source link

solution for creating mulitple plots in a single code chunk #7

Open yihui opened 13 years ago

yihui commented 13 years ago

I think I'm close to a solution for my question a few weeks ago: how to produce multiple plots in a single code chunk (and show them in LaTeX)?

For LaTeX: we can put each plot in a scalebox macro (in the graphicx package). With a proper scaling factor, the plots can be arranged side by side, e.g.

\begin{figure}
\begin{center}
\scalebox{.7}{
    \beginpgfgraphicnamed{newfile1-test1}
    \input{newfile1-test1.tikz}
    \endpgfgraphicnamed
}
\scalebox{.7}{
    \beginpgfgraphicnamed{newfile1-test2}
    \input{newfile1-test2.tikz}
    \endpgfgraphicnamed
}
\end{center}
\caption{a figure bla bla}
\end{figure}

The scaling factor needs to be specified in the code chunk options and let the user adjust it.

For pgfSweave, or actually tikzDevice, what we need is to generate a new tikz file for each plot. This is something like png('Rplot%03d.png') -- automatic increment for file names. I'm not sure if tikz can have a similar functionality.

The Sweave author(s) have been recommending users to write the awkward R code like pdf('some_plot.pdf'); plot(1); dev.off(); cat('\\includegraphics{some_plot}') in Sweave when they want multiple figures. I believe this is a very nasty solution.

yihui commented 13 years ago

BTW, the scale box also provides a possibility for the user to plot with a large canvas, but show the output on a different scale. Sometimes this is useful. R plots cannot preserve proportionality when we use different width/height for the graphics device. This problem is more obvious when we use a small device, e.g.

pdf(width = 3, height = 3)
plot(1)
dev.off()

The margins are too wide. Similar things happen to the tikz device as well. This is why I want to scale the output: I can use a large graphics device to avoid the too wide margins.

cameronbracken commented 13 years ago

This is also a problem that I have encountered. I usually get around it by using layout() or something similar or else just having separate code chunks for different plots. I can see how this might be useful for an arbitrary number of plots though.

The only problem I see with this is the scaling of the graphic, which goes against the tikzDevice and pgfSweave philosophy of consistant font sizing. The option for a separate file for each plot is a good one to implement in tikzDevice.

yihui commented 13 years ago

I fully understand and appreciate the philosophy; actually the scalebox solution I mentioned here is more a solution on putting multiple plots together than really scaling the graphics. We can set the scaling factor to 1 to obey the philosophy, right? It is the ``side-effect'' that is important :-) Or do you have other LaTeX solutions to arranging pgf graphics side by side?

It is absolutely correct that layout() and par(mfrow) are good R solutions, but they are not general solutions. For instance, what if I need to put a ggplot2 plot and a base graphics side by side in one code chunk?

It is a natural idea and a common practice to produce more than one plot in a code chunk, and the restriction of Sweave on `one-graph-per-chunk' is by no means reasonable.

cameronbracken commented 13 years ago

I think I agree. Though the way that Sweave is currently set up, there is a single device opened for each code chunk so the multiple plot idea would have to be implemented at the device level (tikzDevice). Therefore, we would have to know in advance that there were multiple code chunks (a new option)....

yihui commented 13 years ago

a preliminary experiment: https://github.com/downloads/yihui/pgfSweave/multiplot.pdf https://github.com/downloads/yihui/pgfSweave/multiplot.Rnw

cameronbracken commented 13 years ago

I can see the pdf but I cant seem to access the Rnw file, can you repost it?

yihui commented 13 years ago

It seems there was a problem when I uploaded the Rnw file. I did that at school and now I'm at home on another computer. I will try to upload again tomorrow.

Basically we just need to specify the chunk label as someplot%d, and the pdf() device can generate a series of plots based on this name (when fig=T,pdf=T,tikz=F).

yihui commented 13 years ago

I uploaded again: https://github.com/downloads/yihui/pgfSweave/multiplot.Rnw

cameronbracken commented 13 years ago

Thanks. Do you think this would be even useful to include yet? I like it so far but it would only be "proof of concept" since there is no support for tikz.

yihui commented 13 years ago

I'm not sure. Support for tikz depends on when tikz() can accept %d filenames.

You can leave it there for the time being. I don't mind.

baptiste commented 13 years ago

A possible workaround is to use the gridBase package to mix grid and base graphics. It's a bit cumbersome though,

 library(gridBase)
 library(ggplot2)

 par(mfrow=c(1,2))
 plot(1,1) ; plot.new()
 vps <- baseViewports()
 p <- qplot(1:10,1:10)
 print(p, vp=vps$figure)
yihui commented 13 years ago

Such problems can be solved inside the package without asking the users to the additional work, so it might be better to make the users concentrate on writing the Sweave document; when they say "plot", we just faithfully record their plots instead of telling them "you have to take care of the graphics devices/systems...".

Thanks for the hint! It's very helpful. I did not know that before.

cameronbracken commented 13 years ago

This will hopefully be something tikzDevice can do soon.

https://github.com/Sharpie/RTikZDevice/issues/29

cameronbracken commented 13 years ago

This has been done in the tikzDevice source!!!

d0479af

Will definitely be in the next version of tikzDevice, hopefully to coincide with the next version of pgfSweave.

yihui commented 13 years ago

Sounds great! I see we will be able to use filenames like Rplot%03d.tex. Does pgfSweave support including all the individual tikz files in the LaTeX document in the next version?

cameronbracken commented 13 years ago

Yes I plan on putting some functionality for this in the next version of pgfSweave, probably along the lines of a onefile argument that will automatically add the correct numbering then include all the files, not sure the best way to do this yet but I will give it some thought.