Reputation: 93
I have a heat map of US data by state (using dummy data), and I'm trying to get it to run a color gradient continuously from dark red to light red from [0,50] and from light green to dark green from (50,100].
If I try using one gradient from red to green it gets quite brown in the middle and if I run from red to white to green it becomes tough to read with the middle colors. Can anyone help me find a way to perform two continuous color gradients on the same map?
Here is my code:
library(ggplot2)
library(fiftystater)
library(colorplaner)
library(RColorBrewer)
# prepare data frame
data("fifty_states")
dft <- data.frame(state=tolower(rownames(USArrests)), USArrests)
names(dft)[names(dft)=='Murder'] <- 'Var1'
dft<-dft[,-c(3:5)]
# create data
dft$Var1 <- runif(50,0, 100)
# map to each state's data
p <- ggplot(dft, aes(map_id = state)) +
# map points to the fifty_states shape data
geom_map(aes(fill = Var1), map = fifty_states, color = 'gray') +
expand_limits(x = fifty_states$long, y = fifty_states$lat) +
coord_map() +
scale_x_continuous(breaks = NULL) +
scale_y_continuous(breaks = NULL) +
labs(x = "", y = "") +
theme(legend.position = "bottom",
panel.background = element_blank())
p+ fifty_states_inset_boxes()
Going from red to white to green continuously
pc <- p+scale_fill_gradient2(low='darkred',
mid = 'white',
high='darkgreen',
midpoint = 50)
pc + fifty_states_inset_boxes() + theme(legend.position = "right")
I found this palette stuff online, but am totally new to it and wasn't able to find a solution playing with it. But it could be useful and I just don't know enough about it.
#TEST
palette <- colorRampPalette(rev(brewer.pal(11,"Spectral")))
pcn <- p+scale_fill_gradientn(colours = palette(4))
pcn + fifty_states_inset_boxes() + theme(legend.position = "right")
Upvotes: 2
Views: 1052
Reputation: 19716
Here is the idea by Andrew Gustar explained a bit further:
pc <- p + scale_fill_gradientn(colors = c("darkred", "tomato1","palegreen", "darkgreen"),
values = scales::rescale(c(min(dft$Var1),
(max(dft$Var1)-min(dft$Var1))/3,
(max(dft$Var1)-min(dft$Var1))*2/3,
max(dft$Var1))))
pc + fifty_states_inset_boxes() + theme(legend.position = "right")
This is equivalent to: values = c(0, 1/3, 2/3, 1)
scale_fill_gradientn
takes a vector of any number of colors and maps them to the values in your data - you can control the mapping with the values argument which takes the range 0 - 1. scales::rescale
scales an arbitrary range vector to 0 - 1 range.
It's can be visually pleasing to use
quantile(dft$Var1, seq(0, 1, length.out = n)) #n depending on the number of colors
to define the values. Example:
pc <- p+scale_fill_gradientn(colors = c("darkred", "tomato1","palegreen", "darkgreen"),
values = scales::rescale(quantile(dft$Var1, seq(0, 1, length.out=4))))
pc + fifty_states_inset_boxes() + theme(legend.position = "right")
Finally, as Andrew Gustar suggested values = c(0, 0.5, 0.5001, 1))
would provide the gradient you asked in the OP: from dark red to light red from [0,50] and from light green to dark green from (50,100]. Giving:
Upvotes: 3