Combining plots and tables on single PDF page

718 views
Skip to first unread message

Gene

unread,
Aug 10, 2009, 2:57:05 PM8/10/09
to ggplot2
All:

For the last few days I have been trying to create a single page in
PDF with 8 viewports. Four of the viewports are to hold graphics
developed using ggplot2. The other four are to hold simple printouts
of data frames. Creating and placing the four graphs has been real
easy! Getting the data frames to print in the correct viewports has
been a nightmare. The best I can do is to have all the tables print
in the middle of the page, over the graphs and over each other. At
this point, I do not want to learn Latex, Weave (in its various
flavors) and the like. I still need to master R more before I feel
comfortable adding additional layers of complexity. Also,
restrictions on my computer do not allow me to install all Latex
completely. Anyway, here are the key excerpts from the code. If
anyone has any ideas, I would be very appreciative.

Thanks!

Gene

##### Helper function to push individual viewports
##### Source: Hadley, ggplot2, p. 154)

vplayout <- function(x, y)
{
viewport(layout.pos.row = x, layout.pos.col = y)
}

##### Generate Report Page

create_page <- function(rate_ticker)
{

# Assign function outputs to variables

p1 <- full_plot(rate_ticker) # graph
p2 <- daily_diff_plot(rate_ticker) # graph
p3 <- daily_hist_plot(rate_ticker) # graph
p4 <- daily_scatter_plot(rate_ticker) # graph
p5 <- table_1(rate_ticker) # dataframe
p6 <- table_2(rate_ticker) # dataframe
p7 <- table_3(rate_ticker) # dataframe

# Structure the page

plot.new()
pushViewport(viewport(layout = grid.layout(4,2)))

# place graphs in their inidividual viewports - NOTE: This works
fine
print(p1, vp = vplayout(1,1), newpage = FALSE)
print(p2, vp = vplayout(1,2), newpage = FALSE)
print(p3, vp = vplayout(2,1), newpage = FALSE)
print(p4, vp = vplayout(2,2), newpage = FALSE)

# place tables in their inidividual viewports - NOTE: The tables
print oput, but they overwrite the
# graphs and each other.
pushViewport(viewport(layout = grid.layout(3,1)))
par(new = TRUE)
textplot(p5, halign = "center", valign = "center", show.rownames =
FALSE)

pushViewport(viewport(layout = grid.layout(3,2)))
par(new = TRUE)
textplot(p6[1:15,], halign = "center", valign = "center",
show.rownames = FALSE)

pushViewport(viewport(layout = grid.layout(4,1)))
par(new = TRUE)
textplot(p7[1:15,], halign = "center", valign = "center",
show.rownames = FALSE)
}


##### Call function (pass ticker) to generate page

pdf.options(height = 11, width = 8.5, paper = "letter")
pdf("./Output/June2009.pdf")
create_page("US0003M")
dev.off()

Gene

unread,
Aug 10, 2009, 3:04:36 PM8/10/09
to ggplot2
I uploaded a copy of the PDF I am getting. It is called
"June_2009.pdf" so you can see the problem with the output.

hadley wickham

unread,
Aug 11, 2009, 10:56:51 AM8/11/09
to Gene, ggplot2
It's hard to tell without a simple reproducible example, but from the
description of the problem it sounds like textplot (from which
package?) is using base graphics, not grid graphics.

Hadley
--
http://had.co.nz/

Gene

unread,
Aug 11, 2009, 11:06:30 AM8/11/09
to ggplot2
Hadley:

Thanks for the question. I am using the textplot() from the gplots
package.
I could not find anything else that would seem to do the trick of
placing
tables on a graphics device. I will put together a small working
example
soon. In the mean time, I am working on another angle - outputting
all
the graphs and tables as .png files and then assembling them on the
page.
Not ideal, but it is giving me a chance to explore the seemingly
infinite
landscape that is R.

More later.

Thanks again!

Gene
> --http://had.co.nz/- Hide quoted text -
>
> - Show quoted text -

Gene

unread,
Aug 12, 2009, 11:20:51 AM8/12/09
to ggplot2
Here is a working example. I can get the four plots to display
nicely in the
first four viewports I created on the PDF device...but the four tables
I am trying to place on the other four viewports on the same page
using
textplot to first conver them into plots, but they end up on separate
pages.

Any suggestions on this or any other method for getting graphs and
tables to display
on the same page? Again, I would like to stay away from Sweave and
Latex technologies
for now.

Thanks!

Gene


require(ggplot2)
require(gplots)
require(grDevices)
set.seed(1410)
dsmall <- diamonds[sample(nrow(diamonds), 100), ]
dtable <- dsmall[1:10, 1:5]

a <- qplot(carat, price, data = dsmall, colour = color)
b <- qplot(log(carat), log(price), data = dsmall)
c <- qplot(carat, x * y * z, data = dsmall)
d <- qplot(carat, price, data = dsmall, alpha = I(1/10))


pdf("./Output/test.pdf", width = 8, height = 11.5)
grid.newpage()

pushViewport(viewport(layout = grid.layout(4,2)))

print(a, vp = viewport(layout.pos.row = 1, layout.pos.col = 1))
print(b, vp = viewport(layout.pos.row = 1, layout.pos.col = 2))
print(c, vp = viewport(layout.pos.row = 2, layout.pos.col = 1))
print(d, vp = viewport(layout.pos.row = 2, layout.pos.col = 2))
pushViewport(viewport(layout.pos.row = 3, layout.pos.col = 1))
textplot(dtable)
pushViewport(viewport(layout.pos.row = 3, layout.pos.col = 2))
textplot(dtable)
pushViewport(viewport(layout.pos.row = 4, layout.pos.col = 1))
textplot(dtable)
pushViewport(viewport(layout.pos.row = 4, layout.pos.col = 2))
textplot(dtable)


dev.off()


On Aug 11, 10:56 am, hadley wickham <h.wick...@gmail.com> wrote:

baptiste auguie

unread,
Aug 12, 2009, 1:14:52 PM8/12/09
to Gene, ggplot2
Hi,

you could perhaps try the gridBase package, designed to mix Grid and
Base graphics. Here is a small example,

require(ggplot2)
require(gridBase)
require(gplots)
require(grDevices)
set.seed(1410)
dsmall <- diamonds[sample(nrow(diamonds), 100), ]
dtable <- dsmall[1:10, 1:5]

a <- qplot(carat, price, data = dsmall, colour = color)
pdf("test.pdf", width = 10, height = 10)
plot.new()
pushViewport(viewport(layout = grid.layout(2,1)))
print(a, vp = viewport(layout.pos.row = 1, layout.pos.col = 1))
pushViewport(viewport(layout.pos.row = 2, layout.pos.col = 1))
par(plt=gridPLT(), new=TRUE,ps=8)
textplot(dtable,valign="bottom")
dev.off()

The alignment of textplot() on a page seems trickier than a simple
plot(), though. It may be worthwhile writing a similar code in pure
Grid (I once saw some tutorials on tables on Paul Murrell's webpage).

HTH,

baptiste
--
_____________________________

Baptiste Auguié

School of Physics
University of Exeter
Stocker Road,
Exeter, Devon,
EX4 4QL, UK

http://newton.ex.ac.uk/research/emag
______________________________

Gene

unread,
Aug 12, 2009, 1:28:57 PM8/12/09
to ggplot2
Baptiste

Thanks for the suggestion. Hadley had mentioned something along those
same lines. The issue does appear to be - as you suggest - one of
lining up the grid graph device and the base graph device. If you
remove the valign from your code you can see that the table is really
centered on the whole graph device, rather than the viewport. I
suspect the issue lies with the use of the gridPLT() function as I am
not properly converting location between the two grids. I will look
up Murrell's work to see if he has dealt with this issue. Thanks
again for the thoughts.. they have really helped to clarify my
thinking.

Cheers,

Gene
> >> --http://had.co.nz/-Hide quoted text -
>
> >> - Show quoted text -
>
> --
> _____________________________
>
> Baptiste Auguié
>
> School of Physics
> University of Exeter
> Stocker Road,
> Exeter, Devon,
> EX4 4QL, UK
>
> http://newton.ex.ac.uk/research/emag
> ______________________________- Hide quoted text -

baptiste auguie

unread,
Aug 12, 2009, 3:33:22 PM8/12/09
to Gene, ggplot2
If you're willing to play with Grid, I found the document I mentioned earlier,

www.stat.auckland.ac.nz/~paul/grid/doc/R-1.8.0/table.pdf

It seems a little outdated though. I managed to get two basic tables
to work that you might find useful as a starting point,

labels <- c("n", "average", "std.dev")
values <- c(7, 15.833, 9.58)


# with a manual layout, probably not the best route...

the.layout <- grid.layout(3, 2, widths = unit(c(1, 1), "inches"),
heights = unit(rep(1, 3), "lines"))
pushViewport(viewport(layout = the.layout))
for (row in 1:3) {
pushViewport(viewport(layout.pos.col = 1, layout.pos.row = row))
grid.rect()
grid.text(labels[row], x = unit(0.1, "inches"), just = c("left",
"centre"))
popViewport()
pushViewport(viewport(layout.pos.col = 2, layout.pos.row = row))
grid.rect()

grid.text(values[row], x = unit(1, "npc") - unit(0.1, "inches"),
just = c("right", "centre"))
popViewport()
}
popViewport()


# using frames, much easier to wrap in a function

grid.frame(name="gf",
layout = grid.layout(3, 2, width = unit(c(1, 1), "inches"),
heights = unit(rep(1, 3), "lines")),
draw = TRUE)

for (col in 1:2) {
for (row in 1:3) {
grid.place("gf", rectGrob(gp=gpar(fill="grey")), row=row,col=col)
grid.place("gf", textGrob(paste("label",row, ",",col)) , row=row,col=col)
}
}


A more recent document ("Drawing Diagrams with R") provides an example
of automated string width calculation. It would be nice to wrap
something like this into a generic function with a method for
data.frames.


Best wishes,

baptiste

baptiste auguie

unread,
Aug 14, 2009, 9:56:22 AM8/14/09
to ggplot2
I've just posted a (very) rough draft of a texplot-like function on
the r wiki, using Grid graphics,

http://wiki.r-project.org/rwiki/doku.php?id=tips:graphics-grid:table

A few obvious things that could be improved:

- cell borders seem to overlap slightly, resulting in line thickness
variation across the table

- the cell size should be calculated from the maximum stringWidth /
stringHeight for each column / row, at least as an option for elastic
column / row sizes.

- the text should have a gpar() option to specify size, color, etc.

- probably much less efficient than it could be. Not sure where the
problem is...

- ...

Ideas are most welcome.

baptiste

Gene

unread,
Aug 14, 2009, 10:03:22 AM8/14/09
to ggplot2
Baptiste:

Wow... Thanks very much. Combining graphs and texts are something I
will be doing regulalrly in R, so I hope that as I get better at R I
will be able to carry on some of your work. I am a 15 year SAS
programmer which makes the transition to R easier in some respects,
but much more difficult in others. Thanks again for all your
assistance.

Best regards,

Gene

baptiste auguie

unread,
Aug 17, 2009, 2:08:14 PM8/17/09
to ggplot2
This is only marginally relevant to the ggplot2 list, I apologize for this.

In an attempt to tidy up this code I ended up creating a small
package, "gridextra", where I intend to collect various functions
based on Grid. The code is hosted on googlecode[1] and the package
should be built automatically on r-forge[2] for various platforms.

Please feel free to join in and contribute.

Best,

baptiste

library(gridextra)

example("barbedGrob") # a grob with lines and points (type = 'b' of
base graphics)
example("tableGrob") # a grob to display a data.frame
example("arrange") # wrapper around grid.layout to arrange several
ggplot2 objects on a page

[1]: http://code.google.com/p/gridextra/
[2]: http://r-forge.r-project.org/projects/gridextra/

Reply all
Reply to author
Forward
0 new messages