Home > Software engineering >  Displaying annotation over facet_wrap label
Displaying annotation over facet_wrap label

Time:09-18

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: enter image description here

Without the facet_wrap background: enter image description here

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)

enter image description here

  • Related