1

Here's the code I'm using to plot a regression line for each US state, using facet wrapping in ggplot2:

ggplot(data = allYearsSlope, aes(x = year, y = residual)) +
  geom_smooth(method = "lm", se = FALSE) +
  facet_wrap(~ state, ncol = 8) +
  theme(
          strip.text = element_text(size = rel(0.5), face = "bold"),
          panel.background = element_rect(fill = "white"),
          panel.border = element_rect(color="purple",fill=NA),
          plot.background = element_blank(),
          axis.ticks.x = element_blank()
        )  +
  scale_x_continuous(labels = NULL) 

It works fine. But now I'm trying to color the facet panel label (the box that, in this case, contains the name of the state that appears above each panel) according to a value ("blue" or "green") that I'm storing in the dataframe that contains the rest of the data. The color is stored in allYearsSlope$panelColor. Having a really hard time figuring out how to do this.

I've read the solution here: Conditional formatting of panel background in GGplot2. Along with the few other SO answers it refers to. But I don't really see a way to do this coming out of those answers. Any ideas, anyone?

Big thanks for any help.

oneyellowlion
  • 195
  • 1
  • 11
  • 2
    The name of the label box is the _strip_, which might make your searching easier. You can achieve different colored strips with the themed strips functionality of the [ggh4x](https://teunbrand.github.io/ggh4x/articles/Facets.html#themed-strips) package. If you need a demo, please post reproducible data. Thanks. – Allan Cameron Dec 24 '22 at 15:39
  • a (manual) workaround can be foud here: https://stackoverflow.com/questions/70841252/how-to-specify-different-background-colors-for-each-facet-label-in-ggplot2 – Wimpel Dec 24 '22 at 15:44
  • @AllanCameron: Thanks, and, concerning reproduceable code, see my comment below on your plot. My code would be way too messy to use here, but the plot you were kind enough to share is perfect for an example. – oneyellowlion Dec 25 '22 at 16:30

1 Answers1

1

The least hacky way I know of to do this is via the ggh4x package:

library(ggh4x)
#> Loading required package: ggplot2

ggplot(iris, aes(Sepal.Width, Petal.Length)) +
  geom_point() +
  geom_smooth(formula = y ~ x, method = "lm") +
  facet_grid2(.~Species, scales = 'free',
               strip = strip_themed(
                 background_x = list(element_rect(fill = "red"),
                                     element_rect(fill = "green"),
                                     element_rect(fill = "yellow")))) 

Created on 2022-12-24 with reprex v2.0.2


Edit

It's not possible to map strip color as an aesthetic, so this needs to be done by writing your own automation. Instead of passing a list of element_rect manually, we can create a list of element_rect whose fill color is dependent on the properties of a regression each faceted subset. This isn't quite as tricky as it sounds. Here for example, we color the strips according to the slope of the regression line in the panel - red for < 0.5 and green for > 0.5:

library(ggh4x)

ggplot(iris, aes(Sepal.Width, Petal.Length)) +
  geom_point() +
  geom_smooth(formula = y ~ x, method = "lm") +
  facet_grid2(.~Species, scales = 'free',
              strip = strip_themed(
                background_x = lapply(split(iris, iris$Species), function(x) {
                  element_rect(fill = ifelse(
                    coef(lm(Petal.Length ~ Sepal.Width, data = x))[2] < 0.5,
                    "red", 
                    "green"))
                })
                ))

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thanks, @allan. But it looks like this cycles through and reuses the colors in the order they're listed. I need to assign colors based on a condidtion, specifically the value of another column in the dataframe for each row. Can I use ggh4x for that? For example, could you modify your code so that the color of the strip is conditional on whether the slope of the regression line is positive or negative? – oneyellowlion Dec 25 '22 at 16:26