Center diverging continuous color palette around 0?

Hello,

I'm mapping some data with R's diverging color palette RdBu. My values are continuous and some dip below 0. I'm trying to figure out how to center the palette so the values above 0 take on a blue hue, the values below 0 take on a red hue, and those at 0 are white (the center of the RdBu palette). The hue direction is right so far, just not the "center".

Here's a quick reprex with some dummy data. I set the Texas value at 0.0 as a test element.

library(tidyverse)
library(tigris)
library(leaflet)

set.seed(617)

states <- states(cb=T)

# Fake data
dat <- tibble(NAME = states@data$NAME,
              dat = rnorm(56, .2, .15))
# 0.0 Texas
dat[50,2] <- 0.0

new_states <- merge(states, dat)

pal <- colorNumeric("RdBu", domain = new_states$dat)

leaflet() %>%
  addProviderTiles("CartoDB.Positron") %>%
  setView(-98.483330, 38.712046, zoom = 4) %>%
  addPolygons(data = new_states,
              fillColor = ~pal(new_states$dat),
              fillOpacity = 0.7,
              weight = 0.2,
              smoothFactor = 0.2,
              popup = ~ paste0(str_extract(NAME, "^([^,]*)"), "<br>", dat)) %>%
  addLegend(pal = pal,
            values = new_states$dat,
            position = "bottomright",
            title = "Values")

I do most of my interactive mapping using tmap, so there might be a better way in leaflet but I accomplished this by manually set the limits of the palette and scale to be an equal distance from 0. For this data, seemed like -0.5 to 0.5 made the most sense. I create the new scale range and pass that to the domain argument of colorNumeric() as well as the values argument of addLegend.

Full code below with image of resulting map:

library(tidyverse)
library(tigris)
library(leaflet)
library(sp)

set.seed(617)

states <- states(cb=T)

# Fake data
dat <- tibble(NAME = states@data$NAME,
              dat = rnorm(56, .2, .15))
# 0.0 Texas
dat[50,2] <- 0.0

new_states <- merge(states, dat)
scale_range <- c(-0.5, 0.5)

pal <- colorNumeric("RdBu", domain = scale_range)

leaflet() %>%
  addProviderTiles("CartoDB.Positron") %>%
  setView(-98.483330, 38.712046, zoom = 4) %>%
  addPolygons(data = new_states,
              fillColor = ~pal(new_states$dat),
              fillOpacity = 0.7,
              weight = 0.2,
              smoothFactor = 0.2,
              popup = ~ paste0(str_extract(NAME, "^([^,]*)"), "<br>", dat)) %>%
  addLegend(pal = pal,
            values = scale_range,
            position = "bottomright",
            title = "Values")

Rplot

3 Likes

Ah, seems like I had a fundamental misunderstanding of domain!

Thanks @mfherman, you're always so helpful!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.