4

I realize that the align.plots function from the ggExtra package has been deprecated and removed. However, I am using my own version as it seems to provide the specific functionality I need. I have looked into faceting to solve my problem but I don't think it will work for my particular issue. What seems to be the problem is that the top-to-bottom images don't align when I use coord_equal on one of them. This doesn't seem to affect left-to-right though. Here is a simplified (or at least as simple as I can make it) version of what I am trying to achieve.

Create some dummy data frames:

source('https://raw.github.com/jbryer/multilevelPSA/master/r/align.R')
require(psych)
df = data.frame(x=rnorm(100, mean=50, sd=10),
            y=rnorm(100, mean=48, sd=10),
            group=rep(letters[1:10], 10))
dfx = describe.by(df$x, df$group, mat=TRUE)[,c('group1', 'mean', 'n', 'min', 'max')]
names(dfx) = c('group', 'x', 'x.n', 'x.min', 'x.max')
dfy = describe.by(df$y, df$group, mat=TRUE)[,c('group1', 'mean', 'n', 'min', 'max')]
names(dfy) = c('group', 'y', 'y.n', 'y.min', 'y.max')
df2 = cbind(dfx, dfy[,2:ncol(dfy)])
range = c(0,100)

This will setup the three plots:

p1a = ggplot(df2, aes(x=x, y=y, colour=group)) + geom_point() + 
    opts(legend.position='none') +
    scale_x_continuous(limits=range) + scale_y_continuous(limits=range)
p1 = p1a + coord_equal(ratio=1)
p2 = ggplot(df, aes(x=x, y=group, colour=group)) + geom_point() +   
    scale_x_continuous(limits=range) + opts(legend.position='none')
p3 = ggplot(df, aes(x=group, y=y, colour=group)) + geom_point() + 
    scale_y_continuous(limits=range) + opts(legend.position='none')

The alignment top to bottom does not work with coord_equal

grid_layout <- grid.layout(nrow=2, ncol=2, widths=c(1,2), heights=c(2,1))
grid.newpage()
pushViewport( viewport( layout=grid_layout, width=1, height=1 ) )
align.plots(grid_layout, list(p1, 1, 2), list(p3, 1, 1), list(p2, 2, 2))

Broken Plot http://bryer.org/alignplots1.png

The fix is to add respect=TRUE to the grid.layout call:

grid_layout <- grid.layout(nrow=2, ncol=2, widths=c(1,2), heights=c(2,1), respect=TRUE)

But if I don't use coord_equal the alignment works fine:

grid_layout <- grid.layout(nrow=2, ncol=2, widths=c(1,2), heights=c(2,1))
grid.newpage()
pushViewport( viewport( layout=grid_layout, width=1, height=1 ) )
align.plots(grid_layout, list(p1a, 1, 2), list(p3, 1, 1), list(p2, 2, 2))

Working Plot http://bryer.org/alignplots2.png

maj
  • 2,479
  • 1
  • 19
  • 25
jbryer
  • 1,747
  • 3
  • 16
  • 29
  • I cant see the difference between the two plots – James Feb 08 '12 at 17:50
  • @James look at the x scales of the two rightmost plots. They're aligned in the second version. – Gregor Thomas Feb 08 '12 at 17:54
  • But I'm confused about what's wrong with the second version. If not using coord_equal makes things work, just don't use it. – Gregor Thomas Feb 08 '12 at 17:56
  • That's right shujaa. The only difference is that in the first one I use coord_equal for the top right plot. For my purposes it is important that the x and y axis be equal. Thanks. – jbryer Feb 08 '12 at 17:57
  • have you tried kohske's development branch on github? He had some examples similar to yours using gtable. – baptiste Feb 08 '12 at 19:20
  • @shujaa Not using coord_equal would be the easy solution, however doing so significantly changes the interpretation of the figures I am trying to create – jbryer Feb 08 '12 at 20:12
  • @baptiste Thanks for the lead. I will look into Kohske's work. – jbryer Feb 08 '12 at 20:14

3 Answers3

4

ggplot2 now has ggplotGrob(), which may help with this.

First, we need to update the code used to generate the plots:

p1a = ggplot(df2, aes(x=x, y=y, colour=group)) + geom_point()  +
  scale_x_continuous(limits=range) + scale_y_continuous(limits=range)
p1 = p1a + coord_equal(ratio=1) + theme_minimal() + theme(legend.position='none')
p2 = ggplot(df, aes(x=x, y=group, colour=group)) + geom_point() +   
  scale_x_continuous(limits=range) + theme_minimal() + theme(legend.position='none')
p3 = ggplot(df, aes(x=group, y=y, colour=group)) + geom_point() + 
  scale_y_continuous(limits=range) + theme_minimal() + theme(legend.position='none') 
p4 <- ggplot(df, aes(x = group, y = y)) + 
  geom_blank() +
  theme(line = element_blank(),
        rect = element_blank(),
        text = element_blank(),
        title = element_blank())

p4 will be blank; we just need the grob to draw.

Then we load the grid package and draw the grobs in a list arranged in rows and columns using cbind() and rbind().

library(grid)
grid.newpage()
grid.draw(
  cbind(
    rbind(ggplotGrob(p3), ggplotGrob(p4), size = "first"),
    rbind(ggplotGrob(p1), ggplotGrob(p2), size = "first"), 
    size = "first"))

Grid plot

I'm not sure if this method will let you plot p3 in a different width and p2 in a different height, as you have them in the original example; I normally need a grid of similarly-sized graphs, and haven't needed to figure out different sizes.

This answer is partially based on partially based on https://stackoverflow.com/a/17463184/393354

Community
  • 1
  • 1
Tom
  • 694
  • 8
  • 20
3

Here is an example:

m <- matrix(c(3, 1, 0, 2), 2, byrow = T)
lay <- gglayout(m, widths = c(1, 3), heights = c(3, 1))
ggtable(p1, p2, p3, layout = lay)

you can use this by

install.packages('devtools')
library(devtools)
dev_mode()
install_github("ggplot2", "kohske", "cutting-edge")
library(ggplot2)

note that this branch is experimental, so maybe there are bugs.

enter image description here

kohske
  • 65,572
  • 8
  • 165
  • 155
  • If `install_github` does not work well, then download zip from here: https://github.com/kohske/ggplot2/tree/cutting-edge and install it. – kohske Feb 09 '12 at 04:46
  • Thanks kohske, I will definitely look into this. Do you know if this will be part of the ggplot2 release scheduled for March? Since this is for a package I am developing I would rather not depend on a developmental version of ggplot2. – jbryer Feb 09 '12 at 13:00
0

To solve the problem using the align.plots method, specify respect=TRUE on the layout call:

grid_layout <- grid.layout(nrow=2, ncol=2, widths=c(1,2), heights=c(2,1), respect=TRUE)
jbryer
  • 1,747
  • 3
  • 16
  • 29
  • For those interested in how this is used, this graphic is generated using the forthcoming [multilevelPSA package](http://jbryer.github.com/multilevelPSA/). – jbryer Feb 09 '12 at 13:54