如何使用facet_grid或facet_wrap保持条的均匀厚度并切换条的位置? [英] How can I maintain uniform thickness of bars AND switch strip position with facet_grid or 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屋!