6

I want to combine two ggplots with grid.arrange with only one general legend. I managed to combine the two legends with a small trick, but since I removed the legend from the first plot, this one is broader after grid.arrange, of course. How can I get both plotting areas to the same size? And also I would like to have one common x axis label centered below both plots. is that possible with grid.arrange? I know, similar questions have been answered before, but I'm still a newbie to R and the solutions are too complicated or I cannot fit them to my data.

So here are my two datasets:

testxy
  SN strain     est     low      up
1  A     xy 11.6751 11.1480 12.2021
2  B     xy 11.4211 11.1108 11.7314
3  C     xy  2.6603  2.4291  2.8915
4  D     xy  4.5503  4.2972  4.8034

testyz
  SN strain     est     low      up
5  A     yz 22.1761 21.5136 22.8387
6  C     yz 21.4829 21.0251 21.9408
7  B     yz 19.3294 18.8950 19.7639
8  D     yz 19.9990 19.3934 20.6047

And this is the code I have so far. It's close to what I want, but just close:

p1<-ggplot(data=testxy, aes(colour=strain, x=SN, y=est))+
theme(panel.background = element_rect(fill = 'white', colour = 'black'))+
theme(legend.position="none")+
theme(axis.title.x = element_text(size = rel(1.5), vjust=-0.1), 
axis.title.y = element_text(size = rel(1.5), vjust=1), axis.text.y = element_text(size = rel(1.4)), axis.text.x = element_text(hjust = 1, size = rel(1.5)),plot.title = element_text(size = rel(2.5), lineheight=1, face="bold"))+
      theme(plot.margin=unit(c(5,5,5,5),"mm"))+
      labs(x="treatment", y="integral", title="xy")+
      scale_colour_manual(name="strain", values=c(xy="blue"))+
      theme(strip.text.x = element_text(size=12, face="bold"), strip.background = element_rect(colour="black", fill="white"))+
      geom_point(aes(color="xy"), size=5, alpha=0.1, shape=16)+
      geom_errorbar(aes(ymin=low, ymax=up, width=0.2), colour="deepskyblue", size=0.8)+
      scale_y_continuous(breaks=seq(5,20,5), limits=c(2,23.5))

p2<-ggplot(data=testyz, aes(colour=strain, x=SN, y=est))+
  theme(panel.background = element_rect(fill = 'white', colour = 'black'))+
  theme(legend.position="right")+
  theme(axis.title.x = element_text(size = rel(1.5), vjust=-0.1), axis.ticks.y = element_blank(), axis.text.y = element_blank(), axis.text.x = element_text(hjust = 1, size = rel(1.5)), plot.title = element_text(size = rel(2.5), lineheight=1, face="bold"))+
  theme(plot.margin=unit(c(5,5,5,5),"mm"))+
  labs(x="treatment", y=NULL, title="yz")+
  scale_colour_manual(name="strain", values=c(yz="green", xy="blue"))+
  theme(strip.text.x = element_text(size=12, face="bold"), strip.background = element_rect(colour="black", fill="white"))+
  geom_point(aes(color="yz"), size=5, alpha=0.1, shape=16)+
  geom_point(aes(color="xy"), size=0)+
  geom_errorbar(aes(ymin=low, ymax=up, width=0.2), colour="green", size=0.8)+
  scale_y_continuous(breaks=seq(5,20,5), limits=c(2,23.5))+
  scale_x_discrete(limits=c("A", "C", "B", "D"))

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

I tried facetting before. It looks really good, but unfortunately, I need to change the order of the levels on the x axes. So, I think facetting doesn't work for me.

I hope you can help me.

Cheers Anne

Richard Erickson
  • 2,568
  • 8
  • 26
  • 39
Anne
  • 241
  • 1
  • 3
  • 9
  • If you use dput with your data I can experiment in my own R easier (if you do this in addition to the print of the data; we can both read and experiment easy). I am not sure why using facetting wouldn't work; it seems to right solution. – kasterma Jul 16 '15 at 12:48
  • Anne, welcome to SO and nice first post! – Richard Erickson Jul 16 '15 at 12:49
  • See [this answer](http://stackoverflow.com/a/28594060/1412059)? – Roland Jul 16 '15 at 12:55
  • Rolnd, thank you for the link. I saw that answer before. But the code stacks my plots on top of each other and I don't know how to change that to horizontal. I don't really understand what this code is doing. Is there an easier way? It seems to be such a basic problem. – Anne Jul 16 '15 at 13:12
  • Can you please clarify what you mean by "[facetting] looks really good, but unfortunately, I need to change the order of the levels on the x axes. So, I think facetting doesn't work for me". "Is there an easier way?". Yes, that would be facetting. It will give you "one general legend", "plotting areas [of] the same size", "one common x axis label centered below both plots". – Henrik Jul 16 '15 at 13:28
  • Hi Henrik! I described the problem below. I want p1 with an x-axis text "ABCD" and p2 with an x-axis text "ACBD". ggplot orders them always alphabetically, but that doesn't make sense in the way I want to present the data. I don't know how to change the alphabetically ordering. does ths make sense? – Anne Jul 16 '15 at 13:54

2 Answers2

1

You should use facetting:

testxy <- read.table(text = "  SN strain     est     low      up
1  A     xy 11.6751 11.1480 12.2021
2  B     xy 11.4211 11.1108 11.7314
3  C     xy  2.6603  2.4291  2.8915
4  D     xy  4.5503  4.2972  4.8034", header = TRUE)

testyz <- read.table(text = "   SN strain     est     low      up
5  A     yz 22.1761 21.5136 22.8387
6  C     yz 21.4829 21.0251 21.9408
7  B     yz 19.3294 18.8950 19.7639
8  D     yz 19.9990 19.3934 20.6047", header = TRUE)

test <- rbind(cbind(testxy, fac = "xy"),
              cbind(testyz, fac = "yz"))


test$SN1 <- interaction(test$SN, test$fac)
test$SN1 <- ordered(test$SN1, levels = test$SN1)


ggplot(data=test, aes(colour=strain, x=SN1, y=est)) +
  geom_point() + 
  facet_wrap(~ fac, scales = "free_x") +
  scale_x_discrete(labels = setNames(as.character(test$SN), as.character(test$SN1))) 

resulting plot

However, this is not a good plot, since the reader will often not notice that the x-axes are different.

Roland
  • 127,288
  • 10
  • 191
  • 288
0

If the only issue of facetting is the order of levels, it can be resolved by reordering your factor-variable prior to calling ggplot2.

You can specify the order of levels of a factor when converting to a factor.

df = rbind(testxy, testyz)
df$strain <- factor(as.character(df$strain), levels=c('yz','xy'))
ggplot(df, aes(colour=strain, x=SN, y=est))+facet_grid(.~strain)
MrGumble
  • 5,631
  • 1
  • 18
  • 33
  • Thank you for your aswer. Unfortunately, this is not a solution. The order of the treatment on the x-axes need to be different. For "testxy" this needs to be A,B,C,D and for "testyz" it is A,C,B,D. I changed the order already in the dataframes but ggplot orders it alphabetically in both plots to A,B,C,D. – Anne Jul 16 '15 at 13:48
  • If your SN truly is A, B, C, and D, I must advice strongly against swapping two indices on adjacent x-axes, as it approximates misleading the viewer! If B in xy differs from B in yz, then call them two different things (e.g. Bx and By). Then reorder the levels of the factor as A,Bx,C,By,D, and try using ``facet_grid(.~strain, scales='free_x')`` to force ggplot to retrain the x-scale for each facet. – MrGumble Jul 16 '15 at 14:21