0

I want to make a matrix of plots, with the background color coded to correspond with particular columns (i.e., I want the colors I want, and in a particular sequence).


I used info from here Conditionally change panel background with facet_grid? to come up with a way to color code background colors, by column, in a matrix of plots in ggplot2, running in RStudio.

But, previously I had been working with some colorblind colors (I'm not colorblind though), and I can't for the life of me get those colors to change to a new set of colors, even when I clear objects from the global environment in RStudio, then reopen the R script in a new RStudio session. Somehow, by old colors are still remembered.

What I see as output (as a JPG image file) is https://drive.google.com/file/d/1I_5GJHOW8VPZShJ4C61Uayo8zrEMPCDZ/ - you will certainly get other colors when running my code.

Two Questions:

  1. How can I control those colors/assign particular colors to climate$elevation levels?
  2. The approach I've used seems to mask my gridlines within plots - at the bottom of my code you can see I tried to add the gridlines back using 'theme' but it does not work, or is behind the colors of elevation level. Is there a better way to do this?

Here is my code:

# install.packages("ggplot2")
library(ggplot2)

#### create Data ####
#####################
temperature<-c(12,43,15,8,7,9,12,15,14,10,34,27,10,12,33,11,15,7,9,12,25,14,9,10,34,37,10,12,33,15,8,7,9,12,15,14,10,34,37,10,12,33,11,15,7,9,12,15,14,9,10,34,37,10,12,33,15,8,7,9,12,15,14,10,34,37,10,12,33,11,15,7,9,12,15,14,9,10,34,37,10,12,15,14,9,36,10,34,37,10)
hour<-c(2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12,2,4,6,8,10,12)
elevation<-c("Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast","Alpine","Montane","Steppe","Valley","Coast")
region<-c("Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America","Europe","N America","S America")
climate<-data.frame(region,elevation,hour,temperature) # create data frame

# Ensures sequence corresponds to sequence of cave zones
climate$elevation <-factor(climate$elevation,
                      levels = c('Alpine','Montane','Steppe','Valley','Coast'),order=TRUE)

# create plot matrix, background colored by elevation
base<-ggplot(data = climate, aes(hour, temperature)) +
  geom_rect(aes(fill = elevation),xmin = -Inf,xmax = Inf, ymin = -Inf,ymax = Inf,alpha = 0.3) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color="steelblue") +
  labs(title = "Elevation by Region & Time of Day",
       subtitle = "(Temperature)",
       y = "Mean Temperature", x = "Hour of Day") + 
  facet_grid(region ~ elevation)
base

###Plot looks like this to me:
https://drive.google.com/file/d/1I_5GJHOW8VPZShJ4C61Uayo8zrEMPCDZ/
# I'm certain colors will look different for you!

# Trying to add gridlines (does not work)
base + theme(
  panel.background = element_rect(fill = "transparent",colour = NA),
  plot.background = element_rect(fill = "transparent",colour = NA),
  panel.grid.major = element_line(size = 0.5, linetype = 'solid',
                                  colour = "white"), 
  panel.grid.minor = element_blank()
)

Steve T
  • 73
  • 1
  • 11

1 Answers1

2

Actually I got the same colors as you. The reason is that your elevation is an ordered factor. Therefore ggplot2 by default makes use of the viridis color palette.

  1. You can set the fill colors using scale_fill_manual and e.g. a named vector of colors.

  2. There are two options for the grid lines. You can simply add the grid lines manually using geom_h/vline. Or you could set the fill for the plot and panel background to NA and make use of panel.ontop which will plot the panel and the grid lines on top of the plot.

library(ggplot2)

cols <- rev(scales::hue_pal()(5))
cols <- setNames(cols, levels(climate$elevation))
cols
#>    Alpine   Montane    Steppe    Valley     Coast 
#> "#E76BF3" "#00B0F6" "#00BF7D" "#A3A500" "#F8766D"

base <- ggplot(data = climate, aes(hour, temperature)) +
  geom_rect(aes(fill = elevation), xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) +
  scale_fill_manual(values = cols) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color = "steelblue") +
  labs(
    title = "Elevation by Region & Time of Day",
    subtitle = "(Temperature)",
    y = "Mean Temperature", x = "Hour of Day"
  ) +
  facet_grid(region ~ elevation)

breaks_x <- seq(2.5, 10, 2.5)
breaks_y <- seq(10, 40, 10)

base +
  geom_vline(xintercept = breaks_x, color = "white", size = 0.5) +
  geom_hline(yintercept = breaks_y, color = "white", size = 0.5) +
  scale_x_continuous(breaks = breaks_x) +
  scale_y_continuous(breaks = breaks_y)

# Trying to add gridlines (does not work)
base + theme(
  panel.background = element_rect(fill = NA, colour = NA),
  plot.background = element_rect(fill = NA, colour = NA),
  panel.grid.major = element_line(
    size = 0.5, linetype = "solid",
    colour = "white"
  ),
  panel.ontop = TRUE,
  panel.grid.minor = element_blank()
)

stefan
  • 90,330
  • 6
  • 25
  • 51
  • ... ggplot by default using viridis? I thought it was scale_color/fill_hue.... – tjebo Jan 23 '21 at 19:37
  • one never stops to learn. And I was actually occasionally surprised why the diamonds data would plot in different colors lol (never questioning it really) – tjebo Jan 23 '21 at 19:42
  • 1
    @tjebo Haha. Me too. First I looked for something strange. Then I restarted my R Session. Then I restarted R. But still viridis ... and then I saw the `order=TRUE` argument in the factor statement. – stefan Jan 23 '21 at 19:50
  • Wow, thanks this is super helpful. Is it possible to get the gridlines behind the plotted data and in front of the background color? In any case, you got me a lot closer to a professional looking figure. And I learned things! – Steve T Jan 23 '21 at 20:31
  • 1
    Hi Steve. To the best of my knowledge: Unfortunately no. That's the drawback of `panel.ontop` and the reason why added the second approach using `geom_h/vline`. Best S. – stefan Jan 23 '21 at 20:35