Using facet tags and strip labels together in ggplot2
Asked Answered
W

4

8

I'd like to create a figure using ggplot2's facet_grid, like below:

# Load ggplot2 library for plotting
library(ggplot2)

# Plot dummy data
p <- ggplot(mtcars, aes(mpg, wt)) 
p <- p + geom_point() 
p <- p + facet_grid(gear ~ cyl)
print(p)

This is great, but since it's going in a journal article each panel also needs to be labelled with a, b, c, etc. The package egg has a great function for this called tag_facet, which is used as follows:

# Load egg library for tagging
library(egg)
#> Warning: package 'egg' was built under R version 3.5.3
#> Loading required package: gridExtra

# Same plot but with tags for each facet
p <- ggplot(mtcars, aes(mpg, wt)) 
p <- p + geom_point() 
p <- p + facet_grid(gear ~ cyl)
tag_facet(p)

Created on 2019-05-09 by the reprex package (v0.2.1)

As required, I now how letter labels on each panel. But, as you can see, my strip labels have disappeared!

My question: How do I retain my strip labels, whilst also adding tags?

Weiweibel answered 9/5, 2019 at 16:43 Comment(3)
I haven't used it, but package stickylabeller might do what you want.Disentail
@Disentail Thanks, I'll check it out. I'm surprised that there isn't a function native to the tidyverse that does this, as it must be a fairly common problem...Weiweibel
This could be another approach: https://mcmap.net/q/121245/-how-to-add-annotation-on-each-facetSeismic
W
2

Of course, I find a solution immediately after asking. The problem appears to be that tag_facet sets strip labels to element_blank, which can be fixed by calling theme after calling tag_facet.

# Load libraries
library(ggplot2)
library(egg)
#> Warning: package 'egg' was built under R version 3.5.3
#> Loading required package: gridExtra

# Create plot
p <- ggplot(mtcars, aes(mpg, wt)) 
p <- p + geom_point() 
p <- p + facet_grid(gear ~ cyl)
p <- tag_facet(p)
p <- p + theme(strip.text = element_text())
print(p)

Created on 2019-05-09 by the reprex package (v0.2.1)

Weiweibel answered 9/5, 2019 at 16:52 Comment(1)
Maybe also strip.background = element_rect() if you want the background back.Nub
L
9

You can view the code for tag_facet here. As you can see, the function explicitly and deliberately removes the facet strips (see also the "value" in the documentation). You can fix that by creating your own function, and just removing the theme call from the original code:

tag_facet2 <- function(p, open = "(", close = ")", tag_pool = letters, x = -Inf, y = Inf, 
    hjust = -0.5, vjust = 1.5, fontface = 2, family = "", ...) {

    gb <- ggplot_build(p)
    lay <- gb$layout$layout
    tags <- cbind(lay, label = paste0(open, tag_pool[lay$PANEL], close), x = x, y = y)
    p + geom_text(data = tags, aes_string(x = "x", y = "y", label = "label"), ..., hjust = hjust, 
        vjust = vjust, fontface = fontface, family = family, inherit.aes = FALSE)
}

enter image description here

Lucent answered 9/5, 2019 at 16:50 Comment(4)
Thanks for the answer (+1), @iod. I noticed that in the code after asking. I think a simpler solution is just to set strip.text = element_text() to reintroduce the strip labels after adding the tags.Weiweibel
Not sure why that is simpler, but have it your way. I'll just note you also need to reset strip.background, to get the rectangles of the strips. Compare your output with mine in the two answers.Lucent
Perhaps simpler isn't the right word, but it's certainly briefer than redefining the tagging function.Weiweibel
That depends on how frequently you need to do it, I guess. Save the function as a file and source it whenever needed instead of calling on egg. But YMMV, of course.Lucent
D
5

With {tagger} package, this can be made a little simpler. You can install tagger by using devtools::install_github("eliocamp/tagger"). After installing tagger, let's load it.

library(tagger)
library(ggplot2)

# Plot dummy data
p <- ggplot(mtcars, aes(mpg, wt)) 
p <- p + geom_point() 
p + facet_grid(gear ~ cyl) + tag_facets()

enter image description here

Dislimn answered 30/7, 2020 at 11:0 Comment(0)
W
2

Of course, I find a solution immediately after asking. The problem appears to be that tag_facet sets strip labels to element_blank, which can be fixed by calling theme after calling tag_facet.

# Load libraries
library(ggplot2)
library(egg)
#> Warning: package 'egg' was built under R version 3.5.3
#> Loading required package: gridExtra

# Create plot
p <- ggplot(mtcars, aes(mpg, wt)) 
p <- p + geom_point() 
p <- p + facet_grid(gear ~ cyl)
p <- tag_facet(p)
p <- p + theme(strip.text = element_text())
print(p)

Created on 2019-05-09 by the reprex package (v0.2.1)

Weiweibel answered 9/5, 2019 at 16:52 Comment(1)
Maybe also strip.background = element_rect() if you want the background back.Nub
N
2

This can be done using only geom_text() :

data_text <- data.frame(
  cyl   = c(4, 6, 8, 4, 6, 8, 4, 6, 8),
  gear  = c(3, 3, 3, 4, 4, 4, 5, 5, 5)
  label = c('(a)', '(b)', '(c)', '(d)', '(e)', '(f)', '(g)', '(h)', '(i)')
)

ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
facet_grid(gear ~ cyl) +
geom_text(data=data_text, aes(x=12, y=5, label=label), fontface='bold', size=4)

enter image description here

Nub answered 9/5, 2019 at 16:58 Comment(1)
You can add check_overlap = TRUE to geom_text to make them look betterMacintyre

© 2022 - 2025 — McMap. All rights reserved.