ggplot2和gridExtra:完全删除facet_grid中的strip - 不仅仅是不可见

17

我有两张图表,我想将它们叠放在一起,放置方式如下:

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轴。

有什么建议吗?


我的解决方法(在我更熟悉的lattice中)是将条带添加到“简单”图中。 - Dieter Menne
4个回答

10

我的解决方案是找到条纹的宽度,然后将两个图表的边距都设置为零,但将没有条纹的那个缩小一点(即条纹的宽度),使它们看起来大小相同。通过试错,条纹似乎大约有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)

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

enter image description here


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)

enter image description here

## 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

enter image description here

# 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

enter image description here

编辑:或者像baptiste建议的那样,使用gtablerbind()函数:

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"))

1

这里提供另一种解决方案,使用viewportgrid.layout。我创建了两个具有不同布局的视口。然后使用参数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)             

enter image description here


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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接