Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
348 views
in Technique[技术] by (71.8m points)

r - ggplot2: multiple plots with different variables in a single row, single grouping legend

While there are some topics going in the same general direction, I haven't found any that would deal with my issue specifically. Hence a new topic, and thanks in advance for all the help.

Situation

I have two plots, that need to go in a single figure horizontally, e.g.:

library(ggplot2)
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]    
p1 <- qplot(price, carat, data=dsamp, colour=clarity)
p2 <- qplot(price, depth, data=dsamp, colour=clarity)

While the dependent variable differs per plot, the grouping and the independent remains the same. Hence I only need but a single legend in the figure to describe the groups.

What I have tried and what did not work

I have tried to use the solution as described in the R Cookbook. The custom multiplot() function given on that page renders the plots without legends just fine. However, if one needs only a single legend, that function fails. Since one of the graphs would contain the legend, whereas the other not, the width of both graphs would differ in relation to each other (copy the multiplot function from the link mentioned please):

multiplot(p1 + theme(legend.position = "none"),p2,cols=2)

Another potential solution that I have found is the package gridExtra, with this code example. It almost does what I need, except that the graphs are arranged vertically. I tried playing with the function arguments, but could not figure how to arrange the plots horizontally. Hope someone has more experience with that package/issue. Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is solution using package gridExtra and grid.arrange(). First, make three plots - one with legend (p1.leg) and two without legends.

p1.leg <- ggplot(dsamp,aes(price,carat,colour=clarity))+geom_point()
p1<-ggplot(dsamp,aes(price,carat,colour=clarity))+geom_point()+
      theme(legend.position="none")
p2 <-ggplot(dsamp,aes(price,depth,colour=clarity))+geom_point()+
     theme(legend.position="none")

Now you can get just legend from the first plot with function g_legend() that I borrowed from @Luciano Selzer answer to this question.

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)}

leg<-g_legend(p1.leg)

Now you can combine both plots and legend with functions arrangeGrob() and grid.arrange(). In arrangeGrob() you can set widths for columns to get desired proportion between plots and legend.

library(gridExtra)
grid.arrange(arrangeGrob(arrangeGrob(p1,p2),leg,ncol=2,widths=c(5/6,1/6)))

enter image description here

UPDATE

To put all plots in the same row:

grid.arrange(arrangeGrob(p1,p2,leg,ncol=3,widths=c(3/7,3/7,1/7)))

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...