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?
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")
)
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")
)
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.