0

I'm using facet_wrap to look at data from individual replicates at "low power." I want to highlight facet titles by coloring the text of specific values a distinct color. In my actual data, I am using the color element to graph a different variable, so it's unavailable.

A similar thread is here, but the solution is rather clunky.

As an example, I'll demonstrate with the diamonds dataset:

library(tidyverse)

diamonds %>% 
  ggplot(aes(x = carat, y = price))+ 
  geom_point()+
  facet_wrap (cut ~ clarity)

all labels in default colors

I'm most interested in diamonds with "Premium" cut, so I want the facet text that says "Premium" to be red, while everything else stays the same.

I tried defining my color and then adding it through the theme element:

mycolor <- c("Premium" = "red")

diamonds %>% 
  ggplot(aes(x = carat, y = price))+ 
  geom_point()+
  facet_wrap (cut ~ clarity)+
  theme(strip.text = element_text(mycolor))

this produces a warning:

Warning: no font could be found for family "red"
Warning: no font could be found for family "red"
Warning: Unable to calculate text width/height (using zero)

but still generates a graph:

error with graph

Z.Lin
  • 28,055
  • 6
  • 54
  • 94

1 Answers1

0

If you are limited to ggplot2 w/o other newer packages to make life easier, the following brute force approach could be useful:

p <- diamonds %>% 
  ggplot(aes(x = carat, y = price))+ 
  geom_point()+
  facet_wrap (cut ~ clarity)

gp <- ggplotGrob(p)

# grob numbers corresponding to facet strips
gp.num <- grep("strip", gp$layout$name)

for(i in gp.num) {
  if(!is.null(gp$grobs[[i]]$grobs[[1]]$children[[2]]$children[[1]]) &&
     gp$grobs[[i]]$grobs[[1]]$children[[2]]$children[[1]]$label == "Premium") {

    gp$grobs[[i]]$grobs[[1]]$children[[2]]$children[[1]]$gp$col <- "red"

  }
}
rm(i, gp.num)

plot(gp)

result

Do note tweaking this to suit your own use case may require some understanding of the hierarchical relationship among the grobs in gp. I've attempted to jot down some points below for reference:

  • gp$grobs[[i]] = facet strip associated with a single facet panel; it has two child grobs in this case, corresponding to the two rows of facet strip labels since we are using facet_wrap() with two variables. If we were using facet_wrap() with one variable / facet_grid(), it should only have 1 child grob.
  • gp$grobs[[i]]$grobs[[1]] = grob for the first row of the facet strip. We focus on this since we are interested in varying the text based on cut; if we wanted to vary by clarity, we'd look at the ..$grobs[[2]] instead.
  • gp$grobs[[i]]$grobs[[1]]$children[[2]] = title grob for the first row. ..$children[1]] contains the rectangle background, while ..$children[[2]] contains the title.
  • gp$grobs[[i]]$grobs[[1]]$children[[2]]$children[[1]] = the actual text grob, which exists as a child of the title grob.

Happy exploring :)

Z.Lin
  • 28,055
  • 6
  • 54
  • 94
  • Awesome - thanks! that's definitely brute force. What would you suggest with other packages to make life easier? I'm happy to discover new tools! – gromanoibarra Jun 24 '23 at 17:02
  • @gromanoibarra ggh4x by teunbrand has been suggested above. In particular, you may want to check out the themed strips [here](https://cran.rstudio.com/web/packages/ggh4x/vignettes/Facets.html). – Z.Lin Jun 25 '23 at 02:30