ggplot2:在分面条形图中删除未使用的因子,但不要在不同的分面之间产生不同的条形宽度

18
df <- structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 
5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L), .Label = c("1", 
"2", "3", "4", "5", "6", "7"), class = "factor"), TYPE = structure(c(1L, 
2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 
1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 
5L, 6L, 1L, 2L, 3L), .Label = c("1", "2", "3", "4", "5", "6", 
"7", "8"), class = "factor"), TIME = structure(c(2L, 2L, 2L, 
2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 
1L, 1L, 1L), .Label = c("1", "5", "15"), class = "factor"), VAL = c(0.937377670081332, 
0.522220720537007, 0.278690102742985, 0.967633064137772, 0.116124767344445, 
0.0544306698720902, 0.470229141646996, 0.62017166428268, 0.195459847105667, 
0.732876230962574, 0.996336271753535, 0.983087373664603, 0.666449476964772, 
0.291554537601769, 0.167933790013194, 0.860138458199799, 0.172361251665279, 
0.833266809117049, 0.620465772924945, 0.786503327777609, 0.761877260869369, 
0.425386636285111, 0.612077651312575, 0.178726130630821, 0.528709076810628, 
0.492527724476531, 0.472576208412647, 0.0702785139437765, 0.696220921119675, 
0.230852259788662, 0.359884874196723, 0.518227979075164, 0.259466265095398, 
0.149970305617899, 0.00682218233123422, 0.463400925742462, 0.924704828299582, 
0.229068386601284)), .Names = c("ID", "TYPE", "TIME", "VAL"), row.names = c(NA, 
-38L), class = "data.frame")

如果我创建以下绘图:

ggplot(df, aes(x=ID, y=VAL, fill=TYPE)) +
  facet_wrap(~ TIME, ncol=1) +
  geom_bar(position="stack") +
  coord_flip()

绘图

然后我决定在不包含任何数据的分面中抑制任何因子的显示。 我已经参考了各种问题和答案,认为scale = "free"方法是正确的方式(而非drop = TRUE会删除与TIME中未使用值对应的空分面),所以接下来:

ggplot(df, aes(x=ID, y=VAL, fill=TYPE)) +
  facet_wrap(~TIME, ncol=1, scale="free") +
  geom_bar(position="stack") +
  coord_flip()

图表

我的问题是如何防止一个分面有4个条形图而另一个分面只有3个条形图时发生的条形图缩放。在这个人为构造的例子中,效果很微妙,在我的实际数据中更糟糕。理想的输出应该是底部的分面与顶部的分面具有相同的条形宽度,并且具有ID因素1、4和6的垂直轴,因此分面的整体垂直尺寸会减小。

如果您能帮我解决为什么计数会堆叠而不是数字值的问题(现已解决),那就更好了。

悬赏更新:

如我在我的后续 问题 中所述,一个更好的解决方案似乎涉及使用 ggplot_buildggplot_table 并修改 gtable 对象。我相信我可以花时间弄清楚,但我希望有人能给我提供帮助。Koshke已经发布了一些 示例


2
对于额外的加分:也许可以使用小写字母 y 而不是 Y,并且加上 stat = "identity" - joran
谢谢!不过,身份参数是不必要的。 - mindless.panda
还有一个 space='free' 参数可以用于 facet_wrap,也许这正是你要找的。早些时候已经有一个关于此的完美问题,但用户已将其删除... - Justin
很不幸,根据文档和对Joran答案的评论,facet_wrap不支持space="free" - mindless.panda
3个回答

16
这样怎么样:
df$w <- 0.9
df$w[df$TIME == 5] <- 0.9 * 3/4
ggplot(df, aes(x=ID, y=VAL, fill=TYPE)) +
   facet_wrap(~TIME, ncol=1, scale="free") +
   geom_bar(position="stack",aes(width = w),stat = "identity") +
   coord_flip()

在此输入图像描述

我不确定我是否计算正确,但你可以明白我的意思。


聪明!视觉上看起来没问题,我理解你的做法。我看到的问题是条形图的宽度是手动调整的,以补偿不同组别之间因素数量的差异。然而,一旦这种差异很大,比如7个组别对比2个组别,这似乎就会变成一个问题。在这种情况下,我想象底部的组别将会有两个正确宽度的条形,但是有很多空白。这涉及到希望调整整体组别的大小,但这似乎是不可能的。 - mindless.panda
@mindless.panda 是的,听起来你正在寻找一个 space 参数,但是对于 facet_wrap 我不认为它存在(尚未)。 - joran
感谢-在手动调整后,暂时可以使用,希望facet_wrap也能得到spacelabeller。为了完美,我可能会生成单独的图并将它们对齐(通过grid或inkscape,因为我从未实际执行过)。 - mindless.panda

12

如果您可以接受使用垂直条形分割图,facet_grid的效果非常理想:

ggplot(df, aes(x=ID, y=VAL, fill=TYPE)) +
  facet_grid(.~TIME, scale="free_x", space = "free_x") +
  geom_bar(position="stack")

在此输入图像描述

更进一步,你可以旋转图表中的所有元素。如果你将头转90度,现在就得到了你想要的东西 :-)

ggplot(df, aes(x=ID, y=VAL, fill=TYPE)) +
  facet_grid(.~TIME, scale="free_x", space = "free_x") +
  geom_bar(position="stack") +
  opts(legend.text = theme_text(angle=90),
       legend.title = theme_text(angle=90),
       strip.text.x = theme_text(angle=90),
       axis.text.x = theme_text(angle=90),
       axis.text.y = theme_text(angle=90),
       axis.title.x = theme_text(angle=90)
       )

在这里输入图片描述


7

原问题提出已经超过五年,因此我认为应该提供更加实时和简洁的方法。这基本上遵循了这里给出的建议:http://ggplot2.tidyverse.org/reference/facet_grid.html

两个关键参数是space="free_y",它允许每个面板的高度与比例尺的长度成比例,以及scales="free_y",它允许每一列的比例尺有所不同。

coord_flip() 允许条形图水平绘制,并且作为个人偏好,将 facet 的标签旋转在 theme 选项中。

ggplot(df, aes(x=ID, y=VAL, fill=TYPE)) +
  geom_bar(stat="identity") +
  coord_flip() +
  facet_grid(TIME~., scales = "free_y", space = "free_y") +
  theme(strip.text.y = element_text(angle = 0))

enter image description here


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