如何在ggplot2中为分面添加通用标签?

100
我经常需要对数字值进行分面处理。 我希望在补充标题中提供足够的信息来解释这些分面处理的值,类似于轴标题。 标签选项会重复很多不必要的文本,并且对于较长的变量标题无法使用。
有什么建议吗?
默认情况下:
test<-data.frame(x=1:20, y=21:40, facet.a=rep(c(1,2),10), facet.b=rep(c(1,2), each=20))
qplot(data=test, x=x, y=y, facets=facet.b~facet.a)

enter image description here

我想要的是:

enter image description here

我在ggplot中能做到的最好:

qplot(data=test, x=x, y=y)+facet_grid(facet.b~facet.a, labeller=label_both)

enter image description here

根据 @Hendy 的提示,与此类似: 为 ggplot2 图表添加第二个 y 轴 - 让它完美

1
天哪,我刚刚在谷歌上找到了这个,现在看到它是一分钟前提出的。根据他的评论,这个问题似乎在问同样的事情,尽管标题可能暗示了其他方面。很棒的模拟图来说明。这正是我的问题——如果我不必解释我的数字方面类别就好了。图表应该通过一个简单的标签来解释分面变量。 - Hendy
3
我通过电子邮件向 ggplot 的一位主要开发人员 Winston Chang(不知道他的SO账户)进行了咨询。他认为目前还没有这个选项,但可能会考虑添加它。他建议我在 GitHub 上添加一个问题,于是我就这样做了。链接在此 - Hendy
1
在某个时候,我放弃了试图控制R/ggplot2,并使用图像编辑器进行所需的修改。 - Andy
1
我赞同安迪所说的。将图表保存为SVG格式,然后将结果放入矢量编辑器(如Inkscape)中。您可以完美地编辑该图表。在您的情况下,这是一个选择吗? - Christian
2
这里的最佳实践有任何更新吗? - Arthur Yip
显示剩余3条评论
6个回答

50
作为最新的`ggplot2`内部使用`gtable`,修改图形变得非常容易:
library(ggplot2)
test <- data.frame(x=1:20, y=21:40, 
                   facet.a=rep(c(1,2),10), 
                   facet.b=rep(c(1,2), each=20))
p <- qplot(data=test, x=x, y=y, facets=facet.b~facet.a)

# get gtable object
z <- ggplotGrob(p)

library(grid)
library(gtable)
# add label for right strip
z <- gtable_add_cols(z, unit(z$widths[[7]], 'cm'), 7)
z <- gtable_add_grob(z, 
                     list(rectGrob(gp = gpar(col = NA, fill = gray(0.5))),
                          textGrob("Variable 1", rot = -90, gp = gpar(col = gray(1)))),
                     4, 8, 6, name = paste(runif(2)))

# add label for top strip
z <- gtable_add_rows(z, unit(z$heights[[3]], 'cm'), 2)
z <- gtable_add_grob(z, 
                     list(rectGrob(gp = gpar(col = NA, fill = gray(0.5))),
                          textGrob("Variable 2", gp = gpar(col = gray(1)))),
                     3, 4, 3, 6, name = paste(runif(2)))

# add margins
z <- gtable_add_cols(z, unit(1/8, "line"), 7)
z <- gtable_add_rows(z, unit(1/8, "line"), 3)

# draw it
grid.newpage()
grid.draw(z)

enter image description here

当然,你可以编写一个自动添加削减标签的函数。未来版本的ggplot2可能会具备此功能,但不确定。

1
版本0.9.3.1提供了ggplotGrob(),它与ggplot_gtable(ggplot_build())相同。我认为这仍然是最好的方法。 - kohske
这种方法会在有图例时覆盖图例。我想知道是否有方法可以防止这种情况发生。 - papirrin
1
如果我没有错的话,这个解决方案已经失效了,因为一些函数现在已经被弃用了。 - Remi.b
1
@Remi.b 现在试试看 - rawr
3
无法在ggplot2 3.2.1和R 3.6.1中正常工作。没有错误信息,但结果图中缺少标签。 - Calimo
显示剩余3条评论

24

现在有第二坐标轴的选项:https://ggplot2.tidyverse.org/reference/sec_axis.html

# Basic faceted plot
p <- ggplot(mtcars, aes(cyl, mpg)) +
  geom_point() +
  facet_grid(vs ~ am)
    
    # Create a simple secondary axis for the facets (use the appropriate scale_x function)
p + 
  scale_y_continuous(sec.axis = sec_axis(~ . , name = "SECOND Y AXIS", breaks = NULL, labels = NULL)) +
  scale_x_continuous(sec.axis = sec_axis(~ . , name = "SECOND X AXIS", breaks = NULL, labels = NULL))

绘图输出


这太棒了,因为除了ggplot2之外不需要另一个软件包。谢谢! - user11538509
1
MVP在原问题提出9年后给出了一个非常棒的答案。感谢! - Zoltan
3
似乎这只适用于连续数据。 - groceryheist

5
也许还有更好的方法,但你可以:
fac1 = factor(rep(c('a','b'),10))
fac2 = factor(rep(c('a','b'),10))
data = data.frame(x=1:10, y=1:10, fac1=fac1, fac2=fac2)
p = ggplot(data,aes(x,y)) + ggplot2::geom_point() + 
facet_grid(fac1~fac2)
p + theme(plot.margin = unit(c(1.5,1.5,0.2,0.2), "cm"))
grid::grid.text(unit(0.98,"npc"),0.5,label = 'label ar right', rot = 270) # right
grid::grid.text(unit(0.5,"npc"),unit(.98,'npc'),label = 'label at top', rot = 0)   # top

4

非常抱歉回复这个十年前的问题,但是我想说你可以使用ggh4x::facet_nested()在绘图中放置跨度条。缺点是需要额外的包,好处是不需要与gtables混淆。

# install.packages("ggh4x")
library(ggplot2)

test<-data.frame(x=1:20, y=21:40, facet.a=rep(c(1,2),10), facet.b=rep(c(1,2), each=20))

ggplot(test, aes(x, y)) +
  geom_point() +
  ggh4x::facet_nested("Facet B" + facet.b ~ "Facet A" + facet.a)

这是由reprex包(v2.0.1)于2022年9月8日创建的。

免责声明:本人编写了ggh4x。


嗨,我正在尝试使用ggh4x,但是出现了错误。没有叫做'ggh4x'的包。 - Kevin Santos
1
@KevinSantos 你先尝试过 install.packages("ggh4x") 吗? - tjebo
那是我的错误。但现在,在每个方面添加所有选项。我的意思是,在方面A中,显示A和B的所有选项,在方面B中,显示A和B的所有选项。 - Kevin Santos
我不确定这个答案与所需解决方案有何不同。如果您的用例与上述问题不同,请随时发布新问题。 - teunbrand
1
我现在明白了。这里的 + 只是为视图添加另一列,并用给定的字符串替换它。 - Liang Zhang
显示剩余4条评论

1

我推荐使用gridExtra来解决问题。你可以插入文本,也可以使用调用grid.text来获得一些格式选项。

library(ggplot2)
# Basic faceted plot

p <- ggplot(mtcars, aes(cyl, mpg)) +
  geom_point() +
  facet_grid(vs ~ am)

grid.arrange(p,top='Top Label', right='Right Label')

enter image description here


1

除了 kohske 所概述的方法之外,您还可以通过更改添加的框的边框来增加边框。

col=NA

col=gray(0.5), linetype=1

另外,更改

fill=gray(0.5)

for

fill=grey(0.8)

并且

gp=gpar(col=gray(1))

gp=gpar(col=gray(0))

如果您希望新的条形图与分面标签相匹配

z <- gtable_add_grob(z, 
      list(rectGrob(gp = gpar(col = gray(0.5), linetype=1, fill = gray(0.8))),
      textGrob("Variable 1", rot = -90, gp = gpar(col = gray(0)))),
      4, 8, 6, name = paste(runif(2)))

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