21

我正在尝试使用cowplot包来安排要发布的图。
我只希望面板的大小和标签相同。

可重现的例子

library(ggplot2)
library(cowplot)

gg1 <- ggplot(mtcars)+
        geom_point(aes(x=mpg,y=hp))+
        theme_bw()+
        theme(aspect.ratio=1)

gg2 <- ggplot(mtcars)+
        geom_point(aes(x=mpg,y=hp,fill=cyl))+
        facet_wrap(~cyl,ncol=2)+
        theme_bw()+
        theme(aspect.ratio=1,
              legend.position='none')

output <- plot_grid(gg1,gg2, labels = c('A','B'),label_size = 20)
print(output)

该代码生成此图。 在此处输入图像描述

如您所见,水平轴既不匹配,面板的上边缘也不匹配。

alignfrom的论点cowplot不适用于多面图。

有任何想法吗?

4

5 回答 5

9

由于这是关于牛图和复杂对齐的投票最高的问题之一,我想指出,牛图现在确实具有对齐多面图的一些功能。(我是包作者。)但是,它们在这种特殊情况下不起作用!

例如,这有效(使用 中的axis选项plot_grid()):

gg1 <- ggplot(mtcars) +
  geom_point(aes(x=mpg, y=hp)) +
  theme_bw()

gg2 <- ggplot(mtcars)+
  geom_point(aes(x=mpg, y=hp, fill=cyl)) +
  facet_wrap(~cyl, ncol=2) +
  theme_bw() +
  theme(legend.position='none')

plot_grid(gg1, gg2, labels = c('A','B'), label_size = 20,
          align = 'h', axis = 'tb')

在此处输入图像描述

我们还可以执行以下操作,以获得不同类型的对齐(取决于您是否希望将刻面带计为绘图的一部分):

plot_grid(gg1, gg2, labels = c('A', 'B'), label_size = 20,
          align = 'h', axis = 'b')

在此处输入图像描述

现在为什么我说它不适用于这种情况?因为,如果您查看问题中的原始代码,您会发现theme(aspect.ratio=1)我删除了一个设置。只要您不强制使用特定的纵横比,cowplot 就可以对齐绘图,因为它用于对齐绘图的方法通常会修改各个绘图的纵横比。

于 2017-11-24T21:06:12.593 回答
5

这是一个技巧,直到有人想出一个更优雅的答案:您可以使用grid.arrangefrom the gridExtrapackage 更改两个图的相对大小,以便轴对齐。下面w代码中的参数是通过给左侧绘图更多的水平宽度来控制它,从而使其与右侧绘图相比相对更大。

library(gridExtra)

w = 0.512

grid.arrange(gg1, gg2, widths=c(w,1-w), ncol=2)

您还可以使用arrangeGrobandtextGrob将“A”和“B”标题添加到每个绘图。

w = 0.512

grid.arrange(arrangeGrob(textGrob("A", x=0.13, gp=gpar(fontface="bold", cex=1.4)), 
                         gg1, heights=c(0.03,0.97)), 
             arrangeGrob(textGrob("B", x=0.13, gp=gpar(fontface="bold", cex=1.4)), 
                         gg2, heights=c(0.03,0.97)),  
             widths=c(w,1-w), ncol=2)

在任何一种情况下,您都需要w手动调整以使图对齐(这就是使这种方法,容我们说,次优的原因)。的适当值w将根据绘图的物理大小而变化。当我将下面的图保存为 1000 x 500 像素w=0.512时,似乎效果很好。png

在此处输入图像描述

更好的答案可能会涉及类似于此 SO answer的内容,但适用于排列多面和非多面图(或者更一般地说,它们的组成 grobs 之间没有一一对应的图)。

于 2015-08-29T18:50:41.680 回答
4

这是基于这个想法的解决方案

library(ggplot2)
library(grid)
library(gridExtra)
library(gtable)

gtable_frame <- function(g, width=unit(1,"null"), height=unit(1,"null")){
  panels <- g[["layout"]][grepl("panel", g[["layout"]][["name"]]), ]
  ll <- unique(panels$l)
  tt <- unique(panels$t)

  fixed_ar <- g$respect
  if(fixed_ar) { # there lies madness, want to align despite aspect ratio constraints
    ar <- as.numeric(g$heights[tt[1]]) / as.numeric(g$widths[ll[1]])
    height <- width * ar
    g$respect <- FALSE
  }

  core <- g[seq(min(tt), max(tt)), seq(min(ll), max(ll))]
  top <- g[seq(1, min(tt)-1), ]
  bottom <- g[seq(max(tt)+1, nrow(g)), ]
  left <- g[, seq(1, min(ll)-1)]
  right <- g[, seq(max(ll)+1, ncol(g))]

  fg <- nullGrob()
  lg <-  if(length(left))  g[seq(min(tt), max(tt)), seq(1, min(ll)-1)] else fg
  rg <- if(length(right)) g[seq(min(tt), max(tt)), seq(max(ll)+1,ncol(g))] else fg
  grobs = list(fg, g[seq(1, min(tt)-1), seq(min(ll), max(ll))], fg, 
               lg, g[seq(min(tt), max(tt)), seq(min(ll), max(ll))], rg, 
               fg, g[seq(max(tt)+1, nrow(g)), seq(min(ll), max(ll))], fg)
  widths <- unit.c(sum(left$widths), width, sum(right$widths))
  heights <- unit.c(sum(top$heights), height, sum(bottom$heights))
  all <- gtable_matrix("all", grobs = matrix(grobs, ncol=3, nrow=3, byrow = TRUE), 
                       widths = widths, heights = heights)
  all[["layout"]][5,"name"] <- "panel" # make sure knows where the panel is for nested calls
  if(fixed_ar)  all$respect <- TRUE
  all
}


p1 <- ggplot(mtcars)+
  geom_point(aes(x=mpg,y=hp))+
  theme_bw()+
  theme(aspect.ratio=1)

p2 <- ggplot(mtcars)+
  geom_point(aes(x=mpg,y=hp,fill=cyl))+
  facet_wrap(~cyl,ncol=2)+
  theme_bw()+
  theme(aspect.ratio=1,
        legend.position='none')

g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
fg1 <- gtable_frame(g1)
fg2 <- gtable_frame(g2)
grid.newpage()
grid.draw(cbind(fg1, fg2))

在此处输入图像描述

请注意,gtable_frame 函数根据面板包装图,但按设计排除了面板条(我觉得它更令人愉快)。

于 2016-04-01T20:37:26.623 回答
4

更新:egg包现在在 CRAN 上
https://cran.r-project.org/web/packages/egg/index.html


我只想补充一点,@ baptiste创建了一个很棒的实验包 egg,它完成了他在回答中写的内容:

从 github ( https://github.com/baptiste/egg )安装它

library("devtools")
install_github("baptiste/egg")

然后简单地做

library("egg")
ggarrange(gg1, gg2, ncol=2)

您可以手动添加标签:

ap <- ggarrange(gg1,gg2, ncol=2)
ggdraw(ap) + draw_plot_label(label=c("a","b"), x=c(0,0.5), y=c(1,1))

(当我尝试首先将标签添加到各个图时,图没有正确排列。)

于 2017-03-10T15:48:52.597 回答
0

我有一个更简单的解决方案,坚持使用 plot_grid 和原始示例。但是,有些人可能会觉得这有点作弊。可以通过添加嵌套的 NULL 图并调整它们的高/宽比来微调带有 cowplot:plot_grid 的对齐图。这在下面应用:

gg3<-plot_grid(NULL,gg2, NULL, align = 'h', nrow = 3, rel_heights = c(0.06,1,0.06))
plot_grid(gg1,gg3, labels = c('A','B'),label_size = 20)

在此处输入图像描述

于 2019-12-15T15:47:34.800 回答