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

时间:2013-06-17 09:20:43

标签: r ggplot2 gridextra

我有两个图表,我将它们放在另一个之上,方式如下:

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 个答案:

答案 0 :(得分:8)

我的解决方案是找到条带的宽度,然后将两个图形的边距设置为零,但是将没有条带的边缘缩小到略小(条带的宽度),以便它们出现大小相同。通过反复试验,似乎条带大约是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

答案 1 :(得分:1)

这是使用viewportgrid.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)             

enter image description here

答案 2 :(得分: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)

答案 3 :(得分:1)

使用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的建议,使用gtable的{​​{1}}函数:

rbind()