1

Here is some fake data, and a plot:

library(foreach)
library(ggplot2)
dat <- foreach(i = 1:6, .combine = rbind) %do% {
  data.frame(x = rnorm(1000), y = rnorm(1000), fac = as.factor(i))
}

ggplot(dat, aes(x=x, y = y))+
  geom_point(aes(col = x+y))+
  facet_wrap( ~ fac, nrow = 2)

enter image description here

How can I make it look like this? If I didn't care about the common colorbar, I'd use grid.arrange

enter image description here

generic_user
  • 3,430
  • 3
  • 32
  • 56
  • You can make a layout matrix like this: `lay <- rbind(c(1,1,1,1,2,2),c(1,1,1,1,2,2),c(1,1,1,1,3,3),c(1,1,1,1,3,3),c(4,4,5,5,6,6),c(4,4,5,5,6,6))`, and then use `grid.arrange`. I'd recommend turning off the legend for the smaller charts with `show.legend = FALSE` in `geom_point` – Mako212 Oct 09 '18 at 20:56
  • I want to achieve this using facet_wrap if possible, because I want the plots to have a common colorbar. In my real data, they have imperfectly overlapping ranges. – generic_user Oct 09 '18 at 21:02
  • 1
    [grab the legend](https://stackoverflow.com/questions/13649473/add-a-common-legend-for-combined-ggplots) (which points to [this](https://github.com/tidyverse/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs)) so you can then also add the legend separately using grid.arrange mechanics – user20650 Oct 09 '18 at 21:17

2 Answers2

1

I combined some ideas from the comments in your question. You can set the limits to be the same on the x and y axes as well - I did not do it here because I was not sure if it was important to your question,

library(plyr)
library(foreach)
library(ggplot2)
library(dplyr)
library(gridExtra)

dat <- foreach(i = 1:6, .combine = rbind) %do%  {
  data.frame(x = rnorm(1000), y = rnorm(1000), fac = as.factor(i))
}




 #update: added 7th part to the layer matrix for the legend
lay <- rbind(c(1,1,1,1,2,2,7),c(1,1,1,1,2,2,7),
             c(1,1,1,1,3,3,7),c(1,1,1,1,3,3,7),
             c(4,4,5,5,6,6,7),c(4,4,5,5,6,6,7))


gp1 <- ggplot(filter(dat, fac ==1), aes(x=x, y = y))+
  geom_point(aes(col = x+y))+
  #set limits the same on each graph or color gradient
  scale_color_gradient(limits = c(min(dat$x + dat$y),max(dat$x + dat$y)))


gp2 <- ggplot(filter(dat, fac ==2), aes(x=x, y = y))+
  geom_point(aes(col = x+y))+
  scale_color_gradient(limits = c(min(dat$x + dat$y),max(dat$x + dat$y)))

gp3 <- ggplot(filter(dat, fac ==3), aes(x=x, y = y))+
  geom_point(aes(col = x+y))+
  scale_color_gradient(limits = c(min(dat$x + dat$y),max(dat$x + dat$y)))


gp4 <- ggplot(filter(dat, fac ==4), aes(x=x, y = y))+
  geom_point(aes(col = x+y))+
  scale_color_gradient(limits = c(min(dat$x + dat$y),max(dat$x + dat$y)))

gp5 <- ggplot(filter(dat, fac ==5), aes(x=x, y = y))+
  geom_point(aes(col = x+y))+
  scale_color_gradient(limits = c(min(dat$x + dat$y),max(dat$x + dat$y)))


gp6 <- ggplot(filter(dat, fac ==6), aes(x=x, y = y))+
  geom_point(aes(col = x+y))+
  scale_color_gradient(limits = c(min(dat$x + dat$y),max(dat$x + dat$y)))



 # grab legend from one plot
g_legend<-function(a.gplot){
  tmp <- ggplot_gtable(ggplot_build(a.gplot))
  leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
  legend <- tmp$grobs[[leg]]
  return(legend)}

aleg <- g_legend(gp1)
gp1 <- gp1+ theme(legend.position = "none")
gp2 <- gp2+ theme(legend.position = "none")
gp3 <- gp3+ theme(legend.position = "none")
gp4 <- gp4+ theme(legend.position = "none")
gp5 <- gp5+ theme(legend.position = "none")
gp6 <- gp6 + theme(legend.position = "none")


gpls <- lapply(list(gp1,gp2,  gp3,gp4,gp5,gp6), ggplotGrob )

gridExtra::grid.arrange(gpls[[1]], gpls[[2]],
                        gpls[[3]], gpls[[4]],
                        gpls[[5]], gpls[[6]],  
                        #use layout matrix to set sizes
                        layout_matrix=lay, aleg)

Edit - Added plot to answer. enter image description here

Mike
  • 3,797
  • 1
  • 11
  • 30
0

couple of suggestions,

g_legend<-function(p){
  tmp <- ggplotGrob(p)
  tmp$grobs[grepl('guide-box', tmp$layout$name)][[1]]
}


aleg <- g_legend(gp1)
gpls <- lapply(list(gp1,gp2,gp3,gp4,gp5,gp6), 
               function(p) ggplotGrob(p+theme(legend.position = "none")))

lay <- rbind(c(1,1,2,7),
             c(1,1,3,7),
             c(4,5,6,7))

gridExtra::grid.arrange(grobs=c(gpls,list(aleg)), layout_matrix=lay, widths=c(2,2,2,1))

or, alternatively,

lay <- rbind(c(1,1,2),
             c(1,1,3),
             c(4,5,6))

gridExtra::grid.arrange(grobs=gpls, layout_matrix=lay, right=aleg)