How to multiplot a list of graphical objects?

601 views
Skip to first unread message

spoggi

unread,
Aug 23, 2014, 10:32:04 AM8/23/14
to ggp...@googlegroups.com
Hi all,
Using a for loop, I can display (using print function) 4 ggplot graphical objects, and I store them as 4 elements of a list, called obj (see code below).
I now would like to plot these 4 graphical objects as 4 panels in a single page using for example the multiplot function. But then I have the following error message:
Error in tapply(X = X, INDEX = x, FUN = FUN, ...) : 
  arguments must have the same size
Could anyone help?
Thks.

Here is a part of my code:
for (j in 1:4){
  load(filenamej)
...
  obj[[j]]<-ggplot(z[[j]],aes(x=rownames(z[[j]]),y=count,fill=factor(count))) + geom_bar(stat="identity")
#note: rownames have different sizes depending on j
  print(obj[[j]])
}
multiplot(plotlist=obj,cols=2)

Saurabh Agrawal

unread,
Aug 24, 2014, 3:40:16 AM8/24/14
to spoggi, ggp...@googlegroups.com
I think what you need to do is take the print out of the for loop:

png(filename='plot.png')
multiplot(plotlist=obj, cols=2)
dev.off()

Regards
Saurabh


--
--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: https://github.com/hadley/devtools/wiki/Reproducibility
 
To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

---
You received this message because you are subscribed to the Google Groups "ggplot2" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ggplot2+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

David Guy

unread,
Aug 24, 2014, 8:26:28 AM8/24/14
to Saurabh Agrawal, spoggi, ggplot2
You can also try package 'gridExtra' that enables placement of multiple graphical objects (grobs) on a grid.

It has much more flexibility than multiplot().

HTH

David
--
David Guy, PhD
R Statistical Consulting Inc.
Flemington, NJ USA
 
Office: 908-237-5107
Cell:    917-941-5890
Fax:    908-284-0356
Skype: david.guy1213


spoggi

unread,
Aug 25, 2014, 1:17:57 PM8/25/14
to ggp...@googlegroups.com, sylvain....@gmail.com
Hi Saurabh,

Actually I did inser the print function just to confirm that I can plot each graphical object independently. Which is ok. I also get a proper answer when I type summary(obj):

>
summary(obj) Length Class Mode [1,] 9 gg list [2,] 9 gg list [3,] 9 gg list [4,] 9 gg list

BUT then
> png(filename='plot.png')
> multiplot(plotlist=obj,cols=2)
Error in tapply(X = X, INDEX = x, FUN = FUN, ...) : 
  arguments must have same length

I still have this problem! It may be due to the fact that barplots (i.e. my 4 graphical objects) have not the same number of bars?
Sincerely yours.

Dennis Murphy

unread,
Aug 25, 2014, 4:33:30 PM8/25/14
to spoggi, ggplot2
Problem 1: No reproducible example.
Problem 2: You allude to the function multiplot(). Assuming it comes
from an R package and is not one of your own invention, there are at
least six CRAN packages with a function named multiplot(): coefplot,
blowtorch, phonTools, abf2, optiRum and Rmisc, which i got from

library(sos)
findFn("multiplot")

You have not mentioned where your multiplot() function comes from.

David Guy has pointed out a simple solution to your problem:

library(gridExtra)
do.call(grid.arrange, obj)

Note that ggplots are produced from grid graphics, so if you're using
a multiplot() function from somewhere, you should make sure that it
supports grid graphics objects. The gridExtra package does; I have no
idea about the others.

To answer your last question, it is highly unlikely that unequal
numbers of bars are the problem since the plots are saved in separate
objects. Below is a reproducible example.

# Create four data frames - note the unequal number of categories
ds1 <- data.frame(x = sample(LETTERS[1:5], 100, replace = TRUE))
ds2 <- data.frame(x = sample(LETTERS[1:4], 100, replace = TRUE))
ds3 <- data.frame(x = sample(LETTERS[1:6], 100, replace = TRUE))
ds4 <- data.frame(x = sample(LETTERS[1:5], 100, replace = TRUE))

# Create a simple function to plot a single data frame
plotfun <- function(d)
{
require(ggplot2)
ggplot(d, aes(x = x)) + geom_bar(fill = "darkorange")
}

# Create a list of ggplot objects
L <- lapply(paste0("ds", 1:4), function(z) plotfun(get(z)))

# Use do.call() to invoke grid.arrange() on the list of plots
library(gridExtra)
do.call(grid.arrange, L)


## Another way that avoids do.call() and allows
# grid.arrange() arguments to be specified - plot
# objects are in the global environment rather than a list object

p1 <- ggplot(ds1, aes(x = x)) + geom_bar(fill = "darkorange")
p2 <- p1 %+% ds2 # Same plot structure as p1, using data ds2
p3 <- p1 %+% ds3
p4 <- p1 %+% ds4

grid.arrange(p1, p2, p3, p4, ncol = 2)

Dennis

spoggi

unread,
Aug 26, 2014, 1:24:36 PM8/26/14
to ggp...@googlegroups.com, sylvain....@gmail.com
Thanks a lot Dennis for this thorough answer. I finally solved my problem.
Thks again to all for your help.
Reply all
Reply to author
Forward
0 new messages