rggplot2plotbackgroundgeom

How to customize the plot.background in ggplot with multiple colors


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?


Solution

  • 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.