2

I am trying to change the facet label colors of a facet_grid I have. This is an example of a plot I have: enter image description here

and I want the facet boxes (labeled A, B, C) to each be a different color (eg. A = red, B = green, C = blue). I've tried this example which is most similar to what I am trying to do but I keep getting this error when I run the last line of code: Error in grid.Call.graphics(C_setviewport, vp, TRUE) : invalid 'layout.pos.col'

Code:

df <- data.frame(
  type   = c("Small", "X-large", "Medium", "Large", "Small", "X-large", "Medium", "Large", "Small", "X-large", "Medium", "Large"), 
  group   = c("A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C"),
  value = c(22, 40, 31, 60, 26, 24, 22, 18, 30, 70, 60, 50), 
  error = c(10, 9, 3, 11, 15, 10, 13, 9, 14, 20, 17, 15)
)

(df$type = factor(df$type, levels=c("Small","Medium","Large","X-large")))  
plot <- ggplot(df, aes(y=type, size = 15)) + facet_grid(group ~ ., scales="free_y", space="free_y")
plot <- plot + geom_point(aes(x=value),
                          size=3)
plot

dummy <- ggplot(data = df, aes(y=type, size = 15)) + facet_wrap(group ~ ., scales = "free_y") + 
  geom_rect(aes(fill=group), xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  theme_minimal()
dummy <- dummy + geom_point(aes(x=value),
                            size=3)
dummy
 
g1 <- ggplotGrob(plot)
g2 <- ggplotGrob(dummy)

gtable_select <- function (x, ...)
{
  matches <- c(...)
  x$layout <- x$layout[matches, , drop = FALSE]
  x$grobs <- x$grobs[matches]
  x
}

panels <- grepl(pattern = "panel", g2$layout$name)
strips <- grepl(pattern = "strip_t", g2$layout$name)
g2$layout$t[panels] <- g2$layout$t[panels] - 1
g2$layout$b[panels] <- g2$layout$b[panels] - 1

new_strips <- gtable_select(g2, panels | strips | stript)
grid.newpage()
grid.draw(new_strips)

gtable_stack <- function(g1, g2){
  g1$grobs <- c(g1$grobs, g2$grobs)
  g1$layout <- rbind(g1$layout, g2$layout)
  g1
}

new_plot <- gtable_stack(g1, new_strips)
grid.newpage()
grid.draw(new_plot)

I am sorry this is a repeat question but I can't seem to get this code to work or find another solution which works. I've looked at this other form and a few other posts here but cannot find an answer that works. Any idea what I am doing wrong or how to fix this? Is there an easier way to assign multiple fills in ggplot?

Other posts: Change facet label text and background colour Multiple colors in a facet STRIP background

Thank you!

clions226
  • 81
  • 1
  • 9
  • 1
    Here's a quite different approach working off of package **ggtext**: https://stackoverflow.com/questions/60332202/conditionally-fill-ggtext-text-boxes-in-facet-wrap – aosmith Jul 08 '21 at 20:04
  • What's the issue with the answer you linked in your post? When I adapt the answer to your `plot` by replacing `p` with `plot` I get a red A, a green B and a blue C. – stefan Jul 08 '21 at 20:05
  • @stefan I get an error when I replace plot with p: Error in grid.Call.graphics(C_setviewport, vp, TRUE) : invalid 'layout.pos.col' – clions226 Jul 09 '21 at 01:40
  • @aosmith thanks for referencing the other thread. When I use that code (from other thread) it removes the facet plot labels - do you know a work around for that? – clions226 Jul 09 '21 at 02:11

1 Answers1

3

The github version of ggh4x was recently updated to allow these kinds of edits to facet strips. (disclaimer: I'm the author of ggh4x). See example below:

library(ggplot2)
library(ggh4x) # devtools::install_github("teunbrand/ggh4x")

df <- data.frame(
  type   = c("Small", "X-large", "Medium", "Large", "Small", "X-large", "Medium", "Large", "Small", "X-large", "Medium", "Large"), 
  group   = c("A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C"),
  value = c(22, 40, 31, 60, 26, 24, 22, 18, 30, 70, 60, 50), 
  error = c(10, 9, 3, 11, 15, 10, 13, 9, 14, 20, 17, 15)
)

df$type <- factor(df$type, levels=c("Small","Medium","Large","X-large"))
ggplot(df, aes(value, type, size = 15)) + 
  geom_point() +
  facet_grid2(
    group ~ ., scales="free_y", space="free_y",
    strip = strip_themed(
      background_y = list(element_rect(fill = "red"),
                          element_rect(fill = "green"),
                          element_rect(fill = "blue"))
    )
  )

Created on 2021-07-08 by the reprex package (v1.0.0)

A fair word of warning though: I'm still tinkering with this stuff, so eventual formulation may change.

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • this looks like a really sleek solution however I keep getting an error 'Could not find function "facet_grid2"'. When I change that to facet_grid() it says there is an unused argument... I'm trying to figure out what argument is not being used but it seems to be a problem with the facet_grid. Is there something I'm missing? – clions226 Jul 09 '21 at 02:00
  • It's the `strip` argument that regular `facet_grid()` doesn't have. The `facet_grid2()` version doesn't exist on the CRAN version of ggh4x because I added it more recently, so I'm guessing that you need to use the latest version on github for this. – teunbrand Jul 09 '21 at 06:15