I am trying to add labels (a, b, c...) to a plot using facet_wrap, outside the margins of the actual plot. I'd like to have them in the label area, but separate from the facet_wrap label (which is the name of the data group). I can push the text outside the border of the plot using coord_cartesian(clip = "off"), but the label background created by facet_wrap blocks the annotation. I can suppress the label background using theme(strip.background = element_blank()), which makes the annotation visible, but aesthetically I would prefer having the background. Is there any way to make the geom_text annotation appear over, rather than under, the facet_wrap label?
Here is an example:
df <- data.frame(x=rep(1:3, 4), mydat=rep(c('apple', 'kiwi', 'orange', 'pear'), each=3))
labels <- data.frame(mydat=as.factor(c('apple', 'kiwi', 'orange', 'pear')),
label=paste0('(', letters[1:4], ')'))
ggplot(df, aes(x,x))
facet_wrap(~mydat)
geom_point()
geom_text(data = labels, aes(label=label), #geom_text or geom_label
x = -Inf, y = Inf, hjust=0, vjust=0,
inherit.aes = FALSE)
#theme(strip.background = element_blank())
coord_cartesian(clip = "off")
With the facet_wrap background:
Without the facet_wrap background:
CodePudding user response:
One option would be the ggh4x
package which offers some useful extensions of the default facets, e.g. using ggh4x::facet_wrap2
you could add you annotations as a second layer of facets. Additionally ggh4x::facet_wrap2
allows style the two layers separately via the strip
argument:
df <- data.frame(x = rep(1:3, 4), mydat = rep(c("apple", "kiwi", "orange", "pear"), each = 3))
labels <- data.frame(
mydat = as.factor(c("apple", "kiwi", "orange", "pear")),
label = paste0("(", letters[1:4], ")")
)
df <- merge(df, labels, by = "mydat")
library(ggplot2)
library(ggh4x)
ggplot(df, aes(x, x))
facet_wrap2(vars(label, mydat),
strip = strip_themed(
background_x = list(
element_blank(),
element_rect(fill = "grey85")
),
text_x = list(
element_text(hjust = 0),
element_text()
),
by_layer_x = TRUE
)
)
geom_point()
coord_cartesian(clip = "off")
CodePudding user response:
You could lower the 'z' value of the strip panels in the gtable layout. E.g.
g = ggplot(df, aes(x,x))
facet_wrap(~mydat)
geom_point()
geom_text(data = labels, aes(label=label), #geom_text or geom_label
x = -Inf, y = Inf, hjust=0, vjust=0,
inherit.aes = FALSE)
coord_cartesian(clip = "off")
gg = ggplotGrob(g)
gg$layout[grep('strip', gg$layout$name), 'z'] = 0
grid::grid.draw(gg)