Plot two ploygon layers, each with a different scale_fill_gradient

83 views
Skip to first unread message

Cody Schank

unread,
Jul 29, 2016, 8:10:27 PM7/29/16
to ggplot2
I have two spatial variables that I want to show together by plotting one on top of the other with different color gradients, and using transparency. If I use blue on one layer, and red on the other, the output should be purple where the two variables coincide with high values.  Something similar to the attached example map.

This is the code I have tried:

p1 <- ggplot() + geom_polygon(data=counties.df,aes(long,lat,group=group,fill = prediction1), alpha=0.5) + scale_fill_gradient(low="white",high="blue")  + coord_equal() 
p2 <- p1 + geom_polygon(data=counties.df, aes(long,lat,group=group,fill = prediction2), alpha=0.5) + scale_fill_gradient(low="white",high="red") 

Also, tried this:

ggplot() + geom_polygon(data=counties.df,aes(long,lat,group=group,fill = prediction1), alpha=0.5) + scale_fill_gradient(low="white",high="blue")  + geom_polygon(data=counties.df, aes(long,lat,group=group,fill = prediction2), alpha=0.5) + scale_fill_gradient(low="white",high="red") + coord_equal() 

For both of these I get the following message: 
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the existing scale.

Any help would be appreciated. Thanks!
image.png

Brandon Hurr

unread,
Jul 29, 2016, 8:44:44 PM7/29/16
to Cody Schank, ggplot2
Could you supply a working example? 

This is a complex problem. Last I recall you can't supply two color scales, but let's try and see if we can do it.

B

--
--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: https://github.com/hadley/devtools/wiki/Reproducibility
 
To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

---
You received this message because you are subscribed to the Google Groups "ggplot2" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ggplot2+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brandon Hurr

unread,
Jul 29, 2016, 9:36:39 PM7/29/16
to Cody Schank, ggplot2
So... everything I google suggests that two color scales is still not possible or purposefully unpossible. 

What I tried was to combine the scales artificially. I subtracted one scale from the other and used scale_gradient_fill2() to set the midpoint as purple, then used an alpha to turn the color towards "white". 

library(ggplot2)
library(dplyr)
library(tidyr)

datagrid <- expand.grid(a = 1:10, b = 1:10)

dataset <- data.frame(datagrid, c= runif(100), d=runif(100))

dataset %>%
mutate(dc = d - c) %>%
gather(type, alphaval, -dc, -a, -b) %>%
ggplot(data=., aes(x=a, y=b, fill = dc, alpha = alphaval)) +
geom_tile() +
scale_fill_gradient2(low="red", mid = "purple", high="blue") 


I don't know if this is a good approach. I hope someone else will chime in and help if this is way off. 

HTH, 
B

Brandon Hurr

unread,
Jul 29, 2016, 11:34:13 PM7/29/16
to Cody Schank, ggplot2
I asked for help on Twitter and received a useful response. Essentially coding the RGB values manually and using scale colour identity. This is a fine approach, but you have two continuous scales that you want to combine. 



Essentially, I was trying to combine them and plot them, but I don't think my approach was a good one. 

B

Cody Schank

unread,
Jul 30, 2016, 12:46:06 PM7/30/16
to ggplot2, codys...@gmail.com
Thanks Brandon!

Attached is some sample data. I am trying to plot prediction.zeroinfl (in red) and prediction.propDamage (in blue) at the same time, and show where they both have high values.  

Also attached is an example map I made in ArcMap of what I am looking for.
predictions_Arkansas.csv
example_map.jpg

Cody Schank

unread,
Jul 30, 2016, 12:52:45 PM7/30/16
to ggplot2, codys...@gmail.com
Also, here is a good description of this particular type of map, described in cartographic principles.  

Cody Schank

unread,
Jul 30, 2016, 2:57:47 PM7/30/16
to ggplot2, codys...@gmail.com
I followed the principles in the link from the previous message, and used this code:

class1Intervals = classIntervals(counties_join3@data$prediction.zeroinfl,n=3,style="jenks")
counties_join3@data[counties_join3@data$prediction.zeroinfl < class1Intervals$brks[2],"var_class1"] <- "1"
counties_join3@data[counties_join3@data$prediction.zeroinfl > class1Intervals$brks[3],"var_class1"] <- "3"
counties_join3@data[is.na(counties_join3@data$var_class1),"var_class1"] <- "2"
class2Intervals = classIntervals(counties_join3@data$prediction.propDamage,n=3,style="jenks")
counties_join3@data[counties_join3@data$prediction.propDamage < class2Intervals$brks[2],"var_class2"] <- "A"
counties_join3@data[counties_join3@data$prediction.propDamage > class2Intervals$brks[3],"var_class2"] <- "C"
counties_join3@data[is.na(counties_join3@data$var_class2),"var_class2"] <- "B"
counties_join3@data$Bi_class = paste0(counties_join3@data$var_class2,counties_join3@data$var_class1)

counties_join3@data$id = rownames(counties_join3@data)
counties.f = fortify(counties_join3,region="id")
counties.df = join(counties.f, counties_join3@data, by="id")

ggplot(counties.df) + aes(long,lat,group=group,fill = Bi_class) + geom_polygon() + coord_equal() + xlim(c(-124.75, -66.90)) + ylim(c(24.85, 49.4)) + scale_fill_manual(values=c("#e8e8e8","#dfb0d6","#be64ac","#ace4e4","#a5add3","#8c62aa","#5ac8c8","#5698b9","#3b4994")) + theme(panel.background = element_rect(fill = 'white', colour = 'white'))
predictiveMap500yearFlood_bivariateChoropleth.png

Brandon Hurr

unread,
Jul 30, 2016, 3:12:57 PM7/30/16
to Cody Schank, ggplot2
Cody, 

Is that what you want? Seems awful close. I would give that colorplanner package a try since it will show more intermediate values. 

Can you supply a full example with your Arkansas data. Something anyone could copy and paste and get the map too? 

B

Dennis Murphy

unread,
Jul 30, 2016, 3:28:31 PM7/30/16
to Brandon Hurr, Cody Schank, ggplot2
I'd tend to agree with Brandon. The mini-vignette on the Github page
explicitly shows a bivariate choropleth map. You may want to change
the color scheme, but colorplaner looks to do what you want IMO.

Dennis

Cody Schank

unread,
Jul 30, 2016, 4:13:15 PM7/30/16
to ggplot2, brando...@gmail.com, codys...@gmail.com
Thanks for the input.  This code will use the csv I attached earlier so that you can replicate the map I made.

library(tigris)
library(classInt)
library(ggplot2)
library(maptools)

arkansas.geo = counties(state = "Arkansas")

exampleData = read.csv("C:/Users/Cody/Downloads/predictions_Arkansas.csv",header=TRUE,stringsAsFactors=FALSE, colClasses=c("character",rep("character",20)))

arkansas.geo@data = data.frame(arkansas.geo@data, exampleData[match(arkansas.geo@data[,"GEOID"], exampleData[,"GEOID"]),])
arkansas.geo$prediction.zeroinfl <- as.numeric(arkansas.geo$prediction.zeroinfl)
arkansas.geo$prediction.propDamage <- as.numeric(arkansas.geo$prediction.propDamage)

class1Intervals = classIntervals(arkansas.geo$prediction.zeroinfl,n=3,style="jenks")
arkansas.geo[arkansas.geo$prediction.zeroinfl < class1Intervals$brks[2],"var_class1"] <- "1"
arkansas.geo[arkansas.geo$prediction.zeroinfl > class1Intervals$brks[3],"var_class1"] <- "3"
arkansas.geo[is.na(arkansas.geo$var_class1),"var_class1"] <- "2"
class2Intervals = classIntervals(arkansas.geo$prediction.propDamage,n=3,style="jenks")
arkansas.geo[arkansas.geo$prediction.propDamage < class2Intervals$brks[2],"var_class2"] <- "A"
arkansas.geo[arkansas.geo$prediction.propDamage > class2Intervals$brks[3],"var_class2"] <- "C"
arkansas.geo[is.na(arkansas.geo$var_class2),"var_class2"] <- "B"
arkansas.geo$Bi_class = paste0(arkansas.geo$var_class2,arkansas.geo$var_class1)

arkansas.geo@data$id = arkansas.geo@data$GEOID
arkansas.geo.f = fortify(arkansas.geo,region="id")
arkansas.geo.df = join(arkansas.geo.f, arkansas.geo@data, by="id")

ggplot(arkansas.geo.df) + aes(long,lat,group=group,fill = Bi_class) + geom_polygon() + coord_equal() + xlim(c(-94.6, -89.60)) + ylim(c(33.0, 36.5)) + scale_fill_manual(values=c("#e8e8e8","#dfb0d6","#be64ac","#ace4e4","#a5add3","#8c62aa","#5ac8c8","#5698b9","#3b4994")) + theme(panel.background = element_rect(fill = 'white', colour = 'white'))

Brandon Hurr

unread,
Jul 30, 2016, 7:16:32 PM7/30/16
to Cody Schank, ggplot2
Alright, 

I played with it a bit. The installation takes a little while because it wanted to install a lot of stuff that was newer than what I had. That's something I need to ask the author about because a lot of it seemed unnecessary to me. 


library(tigris)
library(classInt)
library(ggplot2)
library(maptools)

library(readr)
library(dplyr)
library(colorplaner) # devtools::install_github("wmurphyrd/colorplaner")

arkansas.geo = counties(state = "Arkansas")

exampleData = read_csv("~/Downloads/predictions_Arkansas.csv")

arkansas.geo.f = fortify(arkansas.geo,region="id")

arkansas.geo.f %>%
full_join(., exampleData, by = c("id" = "GEOID")) %>% 
ggplot(., aes(long, lat, group=group, fill = prediction.propDamage, fill2 = prediction.zeroinfl)) + 
geom_polygon() +
coord_equal() +
xlim(c(-94.6, -89.60)) +
ylim(c(33.0, 36.5)) +
theme(panel.background = element_rect(fill = 'white', colour = 'white')) +
scale_fill_colorplane()


Inline image 1

Looks fairly good. I've put in a github issue about adjusting the color scale itself because I can't see a way to do that from the docs and introduction. I'm wondering if that's on purpose, but the current default is not very colorblind friendly. 

HTH,
B

Brandon Hurr

unread,
Aug 1, 2016, 11:32:10 PM8/1/16
to Cody Schank, ggplot2, Dennis Murphy
I got with Will Murphy on github and he was very responsive. He coded up a red/blue version of the colorplane and the result is attached. 



You have to install a fork of the repo in order to use it though. 

library(tigris)
library(classInt)
library(ggplot2)
library(maptools)

library(readr)
library(dplyr)
library(colorplaner) # devtools::install_github("wmurphyrd/colorplaner", ref = "other_projections")

arkansas.geo = counties(state = "Arkansas")

exampleData = read_csv("~/Downloads/predictions_Arkansas.csv")

arkansas.geo.f = fortify(arkansas.geo,region="GEOID")

arkansas.geo.f %>%
full_join(., exampleData, by = c("id" = "GEOID")) %>% 
ggplot(., aes(long, lat, group=group, fill = prediction.propDamage, fill2 = prediction.zeroinfl)) + 
geom_polygon() +
coord_equal() +
xlim(c(-94.6, -89.60)) +
ylim(c(33.0, 36.5)) +
theme(panel.background = element_rect(fill = 'white', colour = 'white')) +
scale_fill_colorplane(projection="red_blue")

I've asked about further adapting the scale in the issue. But, I'm unsure of implementation. 

Feel free to participate. I suspect this will be useful for many. 

B

On Mon, Aug 1, 2016 at 2:11 PM, Cody Schank <codys...@gmail.com> wrote:
Thanks Brandon! 


red_blue.png
Reply all
Reply to author
Forward
0 new messages