如何安排共享坐标轴? [英] How to arrange plots with shared axes?

查看:177
本文介绍了如何安排共享坐标轴?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个具有共享轴和边缘直方图的三个散点图的排列。这看起来应该很简单,但它给我适合。我已经尝试过使用gridExtra和gtable的方法,这两种方法都得到了我想要的一般安排,但对齐和绘图大小都关闭了。

还有很多其他帖子与这个问题有关,我已经尝试了许多答案,特别是来自@baptiste的答案,因为发布的版本不使用 unit.pmax 作为宽度和高度的单位比较。自定义函数可以从另一个问题借用,以继续使用稳定的gtable版本。




I am trying to create an arrangement of three scatterplots with shared axes and marginal histograms. This seems like it should be simple, but it's giving me fits. I have tried approaches with gridExtra and gtable, both of which have gotten the general arrangement like I want but with alignments and plot sizes that were off.

There are many other posts related to this question and I have experimented with the answers given to many of them, especially answers from @baptiste here and here. The latter's approach to controlling width might be the key to the alignments, but I haven't understood it well enough to adapt it to my problem.

A minimal working example follows, preceded by its result. The result has quite a few problems:

  • The bottom right plot is bigger than the other two. This has been an issue with all approaches, including grid.arrange(), with which I placed a blank rectangle grob to balance the scatter plots.
  • The sizes of the maringal histograms are way off and not what I would expect from the code, which is that their narrow dimension would be about 1/4 the size of the scatter plots' width.
  • The spacing of the plots is too wide.
  • None of the marginal histograms align correctly with the scatter plots.
  • The marginal histogram on the right (c) is so narrow that it doesn't show up at all in the png, yet it does show up (though still too narrow) in the RStudio plot viewer, though only when "zoomed".

Bonus points for an answer that will align the plots' axes correctly even if the width of the axes labels varies between plots as such would be much more adaptable for future problems.

library(ggplot2)
library(grid)
library(gtable)
data <- data.frame(a = rnorm(100, 30, 3), b = rnorm(100, 40, 5), c=rnorm(100, 50, 3))
b_a.scatter <- ggplot(data, aes(x=a, y=b)) + geom_point() + coord_equal(ratio=1, xlim=c(0,100), ylim=c(0,100)) +
  theme(
    axis.text.x  = element_blank(),
    axis.title.x = element_blank(),
    axis.ticks.x = element_blank(),
    plot.margin  = unit(c(1,0,-0.5,1), "cm")
  )

c_a.scatter <- ggplot(data, aes(x=a, y=c)) + geom_point() + coord_equal(ratio=1, xlim=c(0,100), ylim=c(0,100)) +
  theme(plot.margin = unit(c(-0.5,0,0.5,1), "cm"))

c_b.scatter <- ggplot(data, aes(x=b, y=c)) + geom_point() + coord_equal(ratio=1, xlim=c(0,100), ylim=c(0,100)) +
  theme(
    axis.text.y  = element_blank(),
    axis.title.y = element_blank(),
    axis.ticks.y = element_blank(),
    plot.margin  = unit(c(-0.5,0,0.5,0), "cm")
  )

a.hist <- ggplot(data, aes(x=a)) + geom_histogram() + coord_equal(xlim=c(0,100), ratio=1/4) +
  theme(
    axis.text.x  = element_blank(),
    axis.title.x = element_blank(),
    axis.ticks.x = element_blank(),
    axis.text.y  = element_blank(),
    axis.title.y = element_blank(),
    axis.ticks.y = element_blank(),
    plot.margin = unit(c(0,0,1,1), "cm")
  )

b.hist <- ggplot(data, aes(x=b)) + geom_histogram() + coord_equal(xlim=c(0,100), ratio=1/4) +
  theme(
    axis.text.x  = element_blank(),
    axis.title.x = element_blank(),
    axis.ticks.x = element_blank(),
    axis.text.y  = element_blank(),
    axis.title.y = element_blank(),
    axis.ticks.y = element_blank(),
    plot.margin = unit(c(0,0,1,0), "cm")
  )

c.hist <- ggplot(data, aes(x=c)) + geom_histogram() + coord_flip(xlim=c(0,100)) +
  theme(
    axis.text.x  = element_blank(),
    axis.title.x = element_blank(),
    axis.ticks.x = element_blank(),
    plot.margin = unit(c(0,1,0,0), "cm")
  )

blankPanel <- grid.rect(gp=gpar(col="white"))

gt <- gtable(widths  = unit(rep(1,9), "null"),
             heights = unit(rep(1,9), "null"),
             respect=T)
gl <- list(ggplotGrob(b_a.scatter),
             ggplotGrob(c_a.scatter), ggplotGrob(c_b.scatter), ggplotGrob(c.hist),
             ggplotGrob(a.hist), ggplotGrob(b.hist))

gt <- gtable_add_grob(gt, gl,
                l=c(1,1,5,9,1,5),
                r=c(4,4,8,9,4,8),
                t=c(1,5,5,5,9,9),
                b=c(4,8,8,8,9,9))

grid.newpage()
png('multiplot.png')
grid.draw(gt)
dev.off()

解决方案

Here's one approach: combine graphs column by column using rbind, then cbind the three columns. Dummy gtables are provided for the empty cells, they only contain layout information.

library(ggplot2)
library(gtable)
d <- data.frame(a = rnorm(100, 30, 3), 
                b = rnorm(100, 40, 5), 
                c=rnorm(100, 50, 3))

theme_set(theme_bw() + 
            theme(plot.background=element_rect(colour="red",size = 2)))
## define simpler plots
a <- ggplot(d, aes(x=a, y=b)) + geom_point() + xlim(0,100)+ ylim(0,90)
b <- ggplot(d, aes(x=a, y=c)) + geom_point() + xlim(0,100) + ylim(0,90)
c <- ggplot(d, aes(x=b, y=c)) + geom_point() + xlim(0,100) + ylim(0,90)
ah <- ggplot(d, aes(x=a)) + geom_histogram() + 
  xlim(0,100)+ ylim(0,2000000) 
bh <- ggplot(d, aes(x=b)) + geom_histogram() + 
  xlim(0,100) + ylim(0,2000000) 
ch <- ggplot(d, aes(x=c)) + geom_histogram() + 
  coord_flip(xlim=c(0,200000))

pl <- lapply(list(a,b,c,ah,bh,ch), ggplotGrob)

## function to create a dummy table (no grobs, zero size) of the right dim for (r/c)bind
dummy_gtable <- function(g){
  gtable(widths=unit(rep(0,ncol(g)), 'null'), heights=unit(rep(0, nrow(g)), 'null'))
}

left <- rbind(pl[[1]],pl[[2]],pl[[4]])
middle <- rbind(dummy_gtable(pl[[1]]),pl[[3]],pl[[5]])
right <- rbind(dummy_gtable(pl[[1]]),pl[[6]], dummy_gtable(pl[[5]]))
grid.newpage()
grid.draw(cbind(left, middle, right))

Note that I'm using cbind and rbind from my experimental fork of gtable, because the released version does not use unit.pmax as unit comparison for widths and heights. Custom functions could be borrowed from another question to keep using the stable gtable version.

这篇关于如何安排共享坐标轴?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆