rchoroplethr

Want to reverse colors in gradient in choroplethr map


I have a graph working in 'choroplethr' but I would like to reverse the colors of the gradient.

Currently the low is "red" and the high is "blue". I have a situation where a low is a good thing and a high is a bad thing, so I would like the high to be "red".

Data:

df1 <- structure(list(region = c(6001L, 6003L, 6005L, 6007L, 6009L, 
6011L, 6013L, 6015L, 6017L, 6019L, 6021L, 6023L, 6025L, 6027L, 
6029L, 6031L, 6033L, 6035L, 6037L, 6039L, 6041L, 6043L, 6045L, 
6047L, 6049L, 6051L, 6053L, 6055L, 6057L, 6059L, 6061L, 6063L, 
6065L, 6067L, 6069L, 6071L, 6073L, 6075L, 6077L, 6079L, 6081L, 
6083L, 6085L, 6087L, 6089L, 6091L, 6093L, 6095L, 6097L, 6099L, 
6101L, 6103L, 6105L, 6107L, 6109L, 6111L, 6113L, 6115L), value = c(1.6, 
0, 0, 0.2, 0, 0, 0.7, 0.1, 0.1, 1.2, 0.1, 0.3, 0.1, 0.1, 1.4, 
0.2, 0.3, 0, 11.8, 0.2, -0.2, 0, -0.1, 0.5, 0, 0, -0.1, 0.2, 
-0.2, -5, -0.3, 0.1, -1.9, 0.5, -0.1, -2.1, -2.5, -1, -0.5, -0.4, 
0, 0.1, -1.8, 0, 0.3, 0, 0.2, 0.6, -0.5, 0.2, 0.2, 0.1, 0.2, 
0.2, 0.2, -0.8, 0.1, 0.3)), class = "data.frame", row.names = c(NA, 
-58L))

Code:

library(choroplethr)

county_choropleth(df1,
                  legend="Percent\nOver\nExpected\nBased On\nPopulation",
                  num_colors = 0,
                  state_zoom=c("california"))

Again, I would like the gradient to start with low/negative numbers being blue, and higher positive values being red.

I have been trying to change the colors using RColorBrewer and 'scale_color_gradient(low = "blue", high = "red")' among other things, but nothing I have tried so far has worked.


Solution

  • While choroplethr et al. are extremely useful tools for automating the mapping process, it is often difficult (or not possible) to achieve the custom results you want. I am not implying that there isn't a way to achieve what you want using choroplethr alone, but I generally find it easier to stick to using ggplot2.

    With that in mind, here is an alternative that uses data downloaded using the tigris package. This will load an sf object into R that you can then dplyr::left_join() your df1 object to. As the FIPS values are strings in the tigris data (GEOID), they will first be converted to integers so they match your region values.

    Then you can easily apply any ggplot functions to your data. For instance, I have chosen theme_void() as it is the option that most closely resembles the output from your code.

    library(tigris)
    library(sf)
    library(dplyr)
    library(ggplot2)
    
    df1 <- structure(list(region = c(6001L, 6003L, 6005L, 6007L, 6009L, 
    6011L, 6013L, 6015L, 6017L, 6019L, 6021L, 6023L, 6025L, 6027L, 
    6029L, 6031L, 6033L, 6035L, 6037L, 6039L, 6041L, 6043L, 6045L, 
    6047L, 6049L, 6051L, 6053L, 6055L, 6057L, 6059L, 6061L, 6063L, 
    6065L, 6067L, 6069L, 6071L, 6073L, 6075L, 6077L, 6079L, 6081L, 
    6083L, 6085L, 6087L, 6089L, 6091L, 6093L, 6095L, 6097L, 6099L, 
    6101L, 6103L, 6105L, 6107L, 6109L, 6111L, 6113L, 6115L), value = c(1.6, 
    0, 0, 0.2, 0, 0, 0.7, 0.1, 0.1, 1.2, 0.1, 0.3, 0.1, 0.1, 1.4, 
    0.2, 0.3, 0, 11.8, 0.2, -0.2, 0, -0.1, 0.5, 0, 0, -0.1, 0.2, 
    -0.2, -5, -0.3, 0.1, -1.9, 0.5, -0.1, -2.1, -2.5, -1, -0.5, -0.4, 
    0, 0.1, -1.8, 0, 0.3, 0, 0.2, 0.6, -0.5, 0.2, 0.2, 0.1, 0.2, 
    0.2, 0.2, -0.8, 0.1, 0.3)), class = "data.frame", row.names = c(NA, 
    -58L))
    
    # Load counties, join df1 data to counties sf
    california_counties <- counties(state = "CA", cb = TRUE, year = 2023) |>
      mutate(GEOID = as.integer(GEOID)) |>
      left_join(df1, by = c("GEOID" = "region"))
    # Using FIPS code '06' for state 'CA'
    
    # Create state outline
    california <- california_counties |>
      summarise(geometry = st_union(geometry))
    
    # Plot
    ggplot() +
      geom_sf(data = california_counties,
              aes(fill = value),
              colour = "grey50") +
      geom_sf(data = california, colour = "black", fill = NA) +
      scale_fill_gradient2(name = "Percent\nOver\nExpected\nBased On\nPopulation",
                           low = "blue",
                           mid = "white",
                           high = "firebrick",
                           midpoint = 0) +
      theme_void()
    

    1