如何更改单个facet_wrap面板的格式?

15

能否更改单个分面绘图的格式?例如,使用下面的示例代码,是否可以更改cyl = 8绘图的标题或背景颜色?

library(ggplot2)
ggplot(mtcars, aes(x=gear)) + 
  geom_bar(aes(y=gear), stat="identity", position="dodge") +
  facet_wrap(~cyl)

1
这个问题类似,可能会提供灵感:https://dev59.com/H3A75IYBdhLWcg3wrbG_ - Andrie
3个回答

19

您可以修改ggplot2 grobs,例如:

library("ggplot2")
d <- ggplot(mtcars, aes(x=gear)) + 
       geom_bar(aes(y=gear), stat="identity", position="dodge") +
       facet_wrap(~cyl)

grob <- ggplotGrob(d)
strip_bg <- grid.ls(getGrob(grob, "strip.background.rect",
                            grep=TRUE, global=TRUE))$name
panel_bg <- grid.ls(getGrob(grob, "panel.background.rect",
                            grep=TRUE, global=TRUE))$name
strip_text <- grid.ls(getGrob(grob, "strip.text.x",
                              grep=TRUE, global=TRUE))$name
grob <- geditGrob(grob, strip_bg[2], gp=gpar(fill="gray60"))
grob <- geditGrob(grob, panel_bg[2], gp=gpar(fill="darkolivegreen2"))
grob <- geditGrob(grob, strip_text[2], gp=gpar(col="white"))
grid.draw(grob)

geditGrob example

更新:这应该可以与 ggplot2 0.9.3 一起使用。

grob <- ggplotGrob(d)

elem <- grob$grobs$panel2
panel_bg <- grid.ls(getGrob(elem, "panel.background.rect", grep=TRUE))$name
grob$grobs$panel2 <- editGrob(elem, panel_bg, gp=gpar(fill="darkolivegreen"), grep=TRUE)

elem <- grob$grobs$strip_t.1
strip_bg <- grid.ls(getGrob(elem, "strip.background.rect", grep=TRUE))$name
grob$grobs$strip_t.1 <- editGrob(elem, strip_bg, gp=gpar(fill="gray60"), grep=TRUE)

elem <- grob$grobs$strip_t.1
strip_text <- grid.ls(getGrob(elem, "strip.text.x.text", grep=TRUE))$name
grob$grobs$strip_t.1 <- editGrob(elem, strip_text, gp=gpar(col="white"), grep=TRUE)

grid.draw(grob)

+1 但这不再起作用了(grid.ls)。你有任何更新的想法吗? - Simon O'Hanlon
@rcs 我一直在尝试使用你的方法重新设计我的图表的某些方面(使用facet_grid在列中有3个方面)。然而,当我尝试使用panel_border <- grid.ls(getGrob(elem, "panel.border.rect", grep=TRUE))$name时,我收到了一个错误:Error in getGrob(elem, "panel.border.rect", grep = TRUE) : it is only valid to get a child from a "gTree"。是什么导致了这样的行为? - radek
1
@radek 没有可重现的示例很难说。使用 grid 修改 ggplot2 图形是一种脆弱的方式... - rcs
@rcs 感谢提供更多细节。这只是一次尝试,也让我想到了同样的问题。将尝试更努力地使用避免 grid 的解决方案。 - radek
1
@radek:当我遇到那个错误时,是因为带子已被重命名为 strip_t1 而非 strip_t.1。然而,这和其他问题一样,让我认为这种方法真的太不稳定了,不值得推荐。 - Jack Aidley

16

我知道这是一个老问题,原来的发帖者可能早就不在了,但我仍然认为这个问题值得回答,以便未来的搜索者参考。rcs提供的被接受的答案确实可行,但我发现它相当不稳定和hacky。最终,我决定采取一种更为谨慎但更为稳定的方法。使用这种方法,你只能改变背景颜色,但对于我的目的来说已经足够了,对其他人也可能有用,我的方法是使用geom_rect来重新着色背景,像这样:

highlights <- data.frame(cyl=c(8))

ggplot() + 
  geom_rect(data=highlights,aes(xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf), fill='red', alpha=0.2) +
  geom_bar(data = mtcars, aes(x=gear), position="dodge", fill = 'black') +
  facet_wrap(~cyl)

示例图


xmin=-Inf等应该放在aes之外,对吗? - jf328
@jf328 嗯,也许吧?无论如何都可以工作,所以没有必要将它们放在aes内部,但我倾向于这样做,因为我习惯将x、y等放在aes内部,感觉更一致。但你同样可以认为,由于aes是多余的,应该将其删除。 - Jack Aidley

4
这可能会帮助您更接近您想要的内容:
mtcars2 = subset(mtcars, cyl != 8)
   subs = subset(mtcars, cyl == 8)

require(ggplot2)
ggplot(mtcars2, aes(x=gear)) + 
    geom_bar(aes(y=gear, fill = 'black'), stat="identity", position="dodge") +
    geom_bar(data = subs, aes(x = gear), fill = 'blue', binwidth = 1) +
    facet_wrap(~cyl)

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