如何使用facet_grid或facet_wrap保持条的均匀厚度并切换条的位置? [英] How can I maintain uniform thickness of bars AND switch strip position with facet_grid or facet_wrap?

查看:164
本文介绍了如何使用facet_grid或facet_wrap保持条的均匀厚度并切换条的位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用水平条形图显示数据,并用分组变量对其进行分面.由于我想要带有刻面的水平图形,因此我将使用ggstance包中的geom_barh.我有一个数据集,我的观察结果分为几种不同的计数类型.像这样:

library(tidyverse)

data <- tibble(observations = c(1:17), 
           type = c("a", "a", "a", "a", 
                    "b", "b", "b", "b", "b", "b", 
                    "c", "c", "c", "c", "c", "c", "c"),
           n = c(30:46))

这是我的问题.当我使用facet_wrap时,我的条具有不同的宽度:

library(ggstance)    

ggplot(data, aes(x = n, y = reorder(observations, n))) +
 geom_barh(stat = "identity") +
 facet_wrap(~ type, ncol = 1, scales = "free_y")

但是当我使用facet_grid时,由于没有strip.position参数,我无法将条带移到顶部:

ggplot(data, aes(x = n, y = reorder(observations, n))) +
 geom_barh(stat = "identity") +
 facet_grid(type ~ . , scales = "free_y", space = "free_y")

这只是ggplot的怪癖之一,还是有办法操纵它?

解决方案

我不认为ggplot2是用于此目的的,但是与许多其他情况一样,如果您愿意接受grob(而不是ggplot2对象)最终,可以破解解决方案.

这里的基本思想是facet_wrap()允许条带位于任何位置(顶部/左侧/右侧/底部),而fact_grid()允许面板的高度/宽度不同.如果将每个选项的ggplot2结果转换为grob对象,则可以将选项2的面板高度应用于选项1.

第1步.同时基于facet_wrap()和&创建ggplot2对象. facet_grid().将它们转换为grob对象. (注意:我没有安装ggstance软件包,但是通常的geom_col() + coord_flip()应该与此处类似,以说明概念...)

p1 <- ggplot(data, aes(y = n, x = reorder(observations, n))) +
  geom_col() +
  facet_wrap(~ type, ncol = 1, scales = "free_y") +
  coord_flip()
g1 <- ggplotGrob(p1)

p2 <- ggplot(data,
       aes(y = n, x = reorder(observations, n))) +
  geom_col() +
  facet_grid(type ~ . , scales = "free_y", space = "free_y") +
  coord_flip()
g2 <- ggplotGrob(p2)

第2步.取得g1&中面板行的位置g2的布局:

g1.panel.rows <- g1$layout$t[grep("panel", g1$layout$name)] #7 / 12 / 17 in this case
g2.panel.rows <- g2$layout$t[grep("panel", g2$layout$name)] #6 / 8 / 10 in this case

# optional: view the layout & visually check that the above are correct
gtable::gtable_show_layout(g1)
gtable::gtable_show_layout(g2)

# also optional (but recommended): check the current height associated with each panel;
# note that g1 has equal height for each panel, while g2 does not    
> g1$heights[g1.panel.rows]
[1] 1null 1null 1null
> g2$heights[g2.panel.rows]
[1] 4.2null 6.2null 7.2null

第3步.将g2的面板高度应用于g1的面板&查看结果.

g1$heights[g1.panel.rows] <- g2$heights[g2.panel.rows]
grid::grid.draw(g1)

I want to display data with a horizontal bar chart and facet it by a grouping variable. Since I want a horizontal graph with faceting, I'll use geom_barh from the ggstance package. I have a data set where my observations are divided into a few different types with counts. Something like this:

library(tidyverse)

data <- tibble(observations = c(1:17), 
           type = c("a", "a", "a", "a", 
                    "b", "b", "b", "b", "b", "b", 
                    "c", "c", "c", "c", "c", "c", "c"),
           n = c(30:46))

Here's my problem. When I use facet_wrap, my bars have different widths:

library(ggstance)    

ggplot(data, aes(x = n, y = reorder(observations, n))) +
 geom_barh(stat = "identity") +
 facet_wrap(~ type, ncol = 1, scales = "free_y")

But when I use facet_grid, I can't move the strip to the top because there's no strip.position argument:

ggplot(data, aes(x = n, y = reorder(observations, n))) +
 geom_barh(stat = "identity") +
 facet_grid(type ~ . , scales = "free_y", space = "free_y")

Is this just one of the quirks of ggplot or is there a way to manipulate this?

解决方案

I don't think ggplot2 is intended for this purpose, but like many other cases, if you are willing to accept a grob (rather than a ggplot2 object) as the end result, hacking a solution is possible.

The basic idea here is that facet_wrap() allows the strip to be in any position (top / left / right / bottom), while fact_grid() allows the height / width of panels to differ. If we convert the ggplot2 result from each option to a grob object, we can apply the panel heights of option 2 to option 1. Here's how:

Step 1. Create ggplot2 objects based on both facet_wrap() & facet_grid(). Convert them to grob objects. (note: I don't have the ggstance package installed, but the usual geom_col() + coord_flip() should be similar for the purpose of illustrating the concept here...)

p1 <- ggplot(data, aes(y = n, x = reorder(observations, n))) +
  geom_col() +
  facet_wrap(~ type, ncol = 1, scales = "free_y") +
  coord_flip()
g1 <- ggplotGrob(p1)

p2 <- ggplot(data,
       aes(y = n, x = reorder(observations, n))) +
  geom_col() +
  facet_grid(type ~ . , scales = "free_y", space = "free_y") +
  coord_flip()
g2 <- ggplotGrob(p2)

Step 2. Get the location of panel rows in both g1 & g2's layouts:

g1.panel.rows <- g1$layout$t[grep("panel", g1$layout$name)] #7 / 12 / 17 in this case
g2.panel.rows <- g2$layout$t[grep("panel", g2$layout$name)] #6 / 8 / 10 in this case

# optional: view the layout & visually check that the above are correct
gtable::gtable_show_layout(g1)
gtable::gtable_show_layout(g2)

# also optional (but recommended): check the current height associated with each panel;
# note that g1 has equal height for each panel, while g2 does not    
> g1$heights[g1.panel.rows]
[1] 1null 1null 1null
> g2$heights[g2.panel.rows]
[1] 4.2null 6.2null 7.2null

Step 3. Apply g2's panel heights to g1's panels & view the result.

g1$heights[g1.panel.rows] <- g2$heights[g2.panel.rows]
grid::grid.draw(g1)

这篇关于如何使用facet_grid或facet_wrap保持条的均匀厚度并切换条的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆