0

I want to customize the plot background into different colors. Specifically, I want the background to be navy at the top and gray everywhere else, even though I want the plot itself to be white (i.e. overlaid onto the background).

I've tried making the background a custom image, but couldn't get that to work either. Here's the closest visual approximation I've managed:

library(ggplot2)
library(tidyr)
library(grid)

mtcars %>%  
  ggplot(aes(x = wt, y = mpg)) +
  geom_point(color = "red") +
  theme(panel.background = element_rect(fill = "white"),
        plot.background = element_rect(fill = "gray"),
        panel.grid.major = element_line(color = "gray"),
        panel.grid.minor = element_blank(),
        plot.margin = margin(t = 20, r = 10, b = 10, l = 10),
        text = element_text(color = "white")
        )

grid.rect(x = 0.01, y = 1, width = 2, height = 0.2, gp = gpar(fill = "navy", alpha = 1))

But instead of a navy rectangle superimposed on the whole plot, I want it only in the background. Any advice?

  • Package {cowplot} could be worth a try: https://wilkelab.org/cowplot/articles/drawing_with_on_plots.html . Don't turn to the dark side though ;-) https://en.wikipedia.org/wiki/Chartjunk – I_O Jul 06 '23 at 15:16

1 Answers1

0

In the newer versions of R, we can use linear gradient fills in the grid graphics system on which ggplot2 is built. For example, we can create a gradient fill from gray to navy as follows:

mtcars %>%  
  ggplot(aes(x = wt, y = mpg)) +
  geom_point(color = "red") +
  theme(panel.background = element_rect(fill = "white"),
        plot.background = element_rect(fill = grid::linearGradient(
          c('gray', 'gray', 'navy', 'navy'), stops = c(0, 0.05, 0.95, 1),
        x2 = unit(0, 'npc'))),
        panel.grid.major = element_line(color = "gray"),
        panel.grid.minor = element_blank(),
        plot.margin = margin(t = 20, r = 10, b = 10, l = 10),
        text = element_text(color = "white")
  )

enter image description here

If we don't like the fade and just want a solid bar of navy at the top, we just put the stops of the linear gradient arbitrarily close together at, say, 95% of the height of the plotting window.

mtcars %>%  
  ggplot(aes(x = wt, y = mpg)) +
  geom_point(color = "red") +
  theme(panel.background = element_rect(fill = "white"),
        plot.background = element_rect(fill = grid::linearGradient(
          c('gray', 'gray', 'navy', 'navy'), stops = c(0, 0.949, 0.95, 1),
        x2 = unit(0, 'npc'))),
        panel.grid.major = element_line(color = "gray"),
        panel.grid.minor = element_blank(),
        plot.margin = margin(t = 20, r = 10, b = 10, l = 10),
        text = element_text(color = "white")
  )

enter image description here

As already pointed out in the comments, it is a good idea to avoid unnecessary chart junk like this unless it really helps you to convey the message within the data.

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thanks for your advice keeping charts simple. I'll probably end up scrapping these charts anyway; I just wanted to play around with style. However, I copied each of your code examples and was just left with a white background for both. Is there something I'm missing? – obsequious_octahedron Jul 06 '23 at 16:24
  • You need to make sure you are on the latest version of R / grid / ggplot2, and have a suitable graphics device. I use ragg, which you can install with `install.packages('ragg')`. Then use the RStudio menu bar to select Tools -> Global Options -> General -> Graphics -> Backend -> AGG and restart. – Allan Cameron Jul 06 '23 at 16:27