在ggplot2中调整facet-grid/facet_wrap中面板的相对空间

8

有没有办法在facet_gridfacet_wrap中为每个分面更改y轴的高度/长度?

例如,

library(ggplot2)
ggplot(economics_long[economics_long$variable %in% c("pop", "uempmed"),], aes(date, value)) +
    geom_line() +
    facet_grid(variable~., scales = "free_y") +
    theme(strip.background = element_blank())

enter image description here

在上面的图中,我希望流行时间序列的y轴高度/长度是失业率中位数y轴长度的两倍(2:1),尽管这两个时间序列具有不同的y轴刻度。就像Kohske在这里所做的那样,在ggplot2的旧版本中,这在ggplot >=2.0.0中不起作用:

https://kohske.wordpress.com/2010/12/25/adjusting-the-relative-space-of-a-facet-grid/

我知道我可以在facet_grid中指定参数space = "free",但我认为这个参数不能用来设置2:1的y轴比例?
我也不想使用“grid.arrange类型”的解决方案来对齐单独创建的ggplots(在其中我可以使用不同的y轴长度创建2个单独的图),因为我理想情况下想要在这一个facet_wrap图中利用Shiny的交互式ggplot2功能(例如,这里的交互式闪亮部分的例子有一半的页面:http://shiny.rstudio.com/articles/selecting-rows-of-data.html)。

1
你是否曾经找到了解决问题的方法?我问这个问题是因为我有完全相同的疑问。当你有三个网格并且想要它们按比例排列(2:1:1)时,该怎么办呢?使用grid_extra和heights参数很容易实现,但它们在垂直方向上对齐得不太好。 - Franky
很遗憾,目前还没有。也许在过去的一年中,随着ggplot2的更新,可能有一种方法可以实现它,但我不知道。我的猜测是它可能仍然需要在ggplot2源代码中实现,而我对此并不熟悉。 - FXQuantTrader
1个回答

5

有多个选项。

使用 facets,您可以使用 facet_grid(..., space='free_y') 来调整每行的高度以适应 y 轴的长度。但是在您的数据集中,底部行被最小化为单行 (0-25 vs. 200,000 - 320,000)。

当绘制/打印 ggplot2 对象时,它们首先被转换为 gtable 对象。将您的绘图保存为 p,我们可以调用 ggplotGrob 来获取 gtable 对象。这是一个单向过程;一旦转换,就无法将 gtable 转回 ggplot2 对象!

(g <- ggplotGrob(p))
TableGrob (12 x 8) "layout": 18 grobs
    z         cells       name                                    grob
1   0 ( 1-12, 1- 8) background        rect[plot.background..rect.3766]
2   1 ( 6- 6, 4- 4)  panel-1-1               gTree[panel-1.gTree.3696]
3   1 ( 8- 8, 4- 4)  panel-1-2               gTree[panel-2.gTree.3711]
4   3 ( 5- 5, 4- 4)   axis-t-1                          zeroGrob[NULL]
5   3 ( 9- 9, 4- 4)   axis-b-1    absoluteGrob[GRID.absoluteGrob.3725]
6   3 ( 6- 6, 3- 3)   axis-l-1    absoluteGrob[GRID.absoluteGrob.3733]
7   3 ( 8- 8, 3- 3)   axis-l-2    absoluteGrob[GRID.absoluteGrob.3741]
8   3 ( 6- 6, 6- 6)   axis-r-1                          zeroGrob[NULL]
9   3 ( 8- 8, 6- 6)   axis-r-2                          zeroGrob[NULL]
10  2 ( 6- 6, 5- 5)  strip-r-1                           gtable[strip]
11  2 ( 8- 8, 5- 5)  strip-r-2                           gtable[strip]
12  4 ( 4- 4, 4- 4)     xlab-t                          zeroGrob[NULL]
13  5 (10-10, 4- 4)     xlab-b titleGrob[axis.title.x..titleGrob.3714]
14  6 ( 6- 8, 2- 2)     ylab-l titleGrob[axis.title.y..titleGrob.3717]
15  7 ( 6- 8, 7- 7)     ylab-r                          zeroGrob[NULL]
16  8 ( 3- 3, 4- 4)   subtitle  zeroGrob[plot.subtitle..zeroGrob.3763]
17  9 ( 2- 2, 4- 4)      title     zeroGrob[plot.title..zeroGrob.3762]
18 10 (11-11, 4- 4)    caption   zeroGrob[plot.caption..zeroGrob.3764]

所有元素都以网格状布局设置。布局中每一行的高度由g$heights给出:

> g$heights
 [1] 5pt                 0cm                 0cm                 0cm                 0cm                 1null               5pt                 1null               0.396281911581569cm 1grobheight        
[11] 0cm                 5pt    

将“panel-1-1”和“panel-1-2”的坐标与这些高度匹配,您会发现第6个和第8个元素都是1null。您可以将它们更改为任何单位,如厘米(cm),英寸(in),点(pt)等。 1null是其他元素剩余的部分,然后在它们之间划分。因此,我们可以将第6个高度更改为2null(请注意使用双括号)。
> g$heights[[6]] <- unit(2, 'null')
> grid.draw(g)

enter image description here


1
谢谢,我知道这种制作ggplots的方法(我在问题中提到了grid.arrange类型的解决方案)。但我认为这并没有真正回答我的具体问题...我最终想要能够调整facet_wrap中的y轴,以便我可以在Shiny中使用交互式ggplot2图表...请参见我在问题中提供的rstudio链接中带有facet_wrap的brushed points示例。我不知道是否可能使用grob实现这样的效果。 - FXQuantTrader
不清楚brushedPoints的工作原理;我的猜想是它不能识别图表上的各个点,而是推断所覆盖的x-和y坐标,并返回在该区域内的任何给定数据框中的点。请注意,该函数不会从ggplot对象中读取数据框,而必须明确给出;此外,您还必须指定使用哪些分面。如果您尝试以您正在尝试的方式组合这两个函数,那么您将有很多工作要做;相反,请尝试使用两个单独的输出绘图小工具。 - MrGumble

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