16

我有两个图表,我按以下方式将一个放在另一个之上:

library(ggplot2)
library(gridExtra)
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- p2 + facet_grid(cyl ~ .)
grid.arrange(p1, p2, ncol=1)

为此,我需要将顶部和底部图的 x 轴对齐,但是由于左侧的条带,多面图比顶部图更窄。我可以使用以下方法使条带不可见:

theme(strip.text.y = element_blank())
theme(strip.background = element_blank())

然而,这并没有消除条带占用的空间。所以我要么需要一种完全摆脱条带的方法,要么有一种方法将我的多面图拆分为单独的图,但以某种方式在它们之间共享相同的 y 轴标签。在我的图表中,我有两个不是很高的多面面板,并且没有足够的空间让它们每个都有一个合适大小的 y 轴。

有什么建议么?

4

4 回答 4

9

我的解决方案是找到条带的宽度,然后将两个图的边距设置为零,但将没有条带的那个缩小到略小(条带的宽度),使它们看起来大小相同。通过反复试验,条带似乎大约有 0.5 行宽(但我想你可以通过编程方式解决这个问题)。因此,只需确保没有带文本的绘图中的正确绘图边距比不可见带的绘图边缘大 0.5 行:

#  Add a line of width 0.5 on the left but set all other margins to zero
p1 <- p1 + theme( plot.margin = unit( c(0,0.5,0,0) , units = "lines" ) )
#  Set all margins to zero, the strip will take up a phantom amount of invisible space
p2 <- p2 + theme(strip.text.y = element_blank() , 
  strip.background = element_blank(),
  plot.margin = unit( c(0,0,0,0) , units = "lines" ) )

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

显然,您可以根据需要调整边距(例如,将 1 添加到每个数字向量中的第一个位置,plot.margin以获得沿每个图顶部的一条线的边框),只要您在右边框中保留 0.5 行的边距在第二个情节中,它们看起来相同。

在此处输入图像描述

于 2013-06-17T10:10:32.650 回答
2

使用包中的函数的另一种解决方案gtable。它对齐图,但保留带状文本。它使用一个gtable函数在 的右侧插入一列,该列p1等于 的条形文本的宽度p2

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

p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- p2 + facet_grid(cyl ~ .)

g1 = ggplotGrob(p1)
# gtable_show_layout(g1)  # View the layout
# g1$widths               # Get the widths of g1

g2 = ggplotGrob(p2)
# gtable_show_layout(g2)  # View the layout
# g2$widths               # Check the widths of g2

#  Add new column to the right of g1 equal in width the strip width of g2.
#  In g2, strip width is the 6th element the vector g2$widths
g1 <- gtable_add_cols(g1, g2$widths[6])  
grid.arrange(g1, g2, ncol=1)

在此处输入图像描述

## But note that if the y-axis titles and/or labels take up different widths, 
#  the two plots are not aligned
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() +
   theme(axis.title.y = element_text(vjust = .5, angle = 0, size = 30))
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- p2 + facet_grid(cyl ~ .)

g1 = ggplotGrob(p1)
g2 = ggplotGrob(p2)

g1 <- gtable_add_cols(g1, g2$widths[6])  # New column added to the right
grid.arrange(g1, g2, ncol=1)             # Plots are not aligned

在此处输入图像描述

# Need to set widths to the maximums in the two plots, 
# i.e., set g2 widths to be the same as g1 widths
g2$widths <- g1$widths
grid.arrange(g1, g2, ncol=1)            # Plots are aligned

在此处输入图像描述

编辑:或者按照 baptiste 的建议,使用gtable'srbind()函数:

g1 = ggplotGrob(p1)
g2 = ggplotGrob(p2)

g1 <- gtable_add_cols(g1, g2$widths[6], 5)  # New column added to the right 

library(grid)
grid.draw(rbind(g1, g2, size = "first"))
于 2014-06-03T02:15:33.750 回答
1

viewport这里使用and的另一个解决方案grid.layout。我创建了 2 个具有 2 个不同布局的视口。然后我使用参数 vp 放置 ggplot2 图。

library(grid)
pushViewport(plotViewport(c(1,1,1,1),layout = grid.layout(2, 1)))
print(p2, vp = viewport(layout.pos.row = 2, layout.pos.col = 1))
pushViewport(viewport(layout.pos.row=1,
  layout = grid.layout(1, 2,widths = unit(c(1,1),c("null",'lines')))))
print(p1, vp = viewport(layout.pos.row = 1, layout.pos.col = 1))
upViewport(2)             

在此处输入图像描述

于 2013-06-17T10:54:42.840 回答
1

您也可以这样做并保留带标题,这将是相关信息:

library(ggplot2)
library(gridExtra)
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() +
         xlab(NULL)
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() +
         facet_wrap( ~ cyl, ncol = 1)
grid.arrange(p1, p2, ncol=1)
于 2013-06-18T20:46:44.260 回答