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
362 views
in Technique[技术] by (71.8m points)

r - Top to bottom alignment of two ggplot2 figures

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

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

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


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

...