2

Data: Zipped ea.ml1 shapefile can be found here, and the country outline can be downloaded here at the GADM site. I've been using the Ethiopia ESRI shapefile. Branch locations are here.

Per the suggestion of user cengel, I have started converting a map project of mine to ggplot2. Data is listed above, and here's my code:

#load in required libraries 
library(ggplot2)
library(maptools)
library(rgdal)
library(rgeos)
library(raster)
library(plyr)

#set working directory setwd("D:/Mapping-R/Ethiopia")

#read in data/shapefiles ea.ml1 <- readOGR(dsn = "D:/Mapping-R/Ethiopia", layer = "EA201507_ML1") eth <- readOGR(dsn = "D:/Mapping-R/Ethiopia", layer = "ETH_adm0") regions <- readOGR(dsn = "D:/Mapping-R/Ethiopia", layer = "ETH_adm1") branches <- read.csv("Branches_Africa.csv", header = TRUE)

#remove all unwanted columns from eth shapefile eth <- eth[, -(2:67)]

#clip ethiopia to ml1 background, fortify to data frame eth.clip1 <- intersect(ea.ml1, eth)

#explicitly identify attribute rows by the .dbf offset, #convert to data frame, making each polygon attribute a point #join points to attributes to fill polygon eth.clip1@data$id <- rownames(eth.clip1@data) eth.f <- fortify(eth.clip1, region = "id") eth.df <- join(eth.f, eth.clip1@data, by = "id")

#converts integers to factors for ggplot eth.df$ML1 <- as.factor(eth.df$ML1)

#fortify regions overlay suitable for mapping regions <- fortify(regions)

#deselect branches without shares, select Ethiopia subset (clip), convert to numbers branches <- branches[branches$share != " . ", ] branches <- branches[branches$CO == "ET", ] branches$share <- as.numeric(as.character(branches$share))

#plot ggplot() + geom_polygon(data = eth.df, aes(long, lat, group = group, fill = ML1)) + scale_fill_manual(values = c("gray", "yellow", "orange", "red")) + geom_path(data = regions, aes(long, lat, group = group), color = "darkgray") + coord_equal()

Using the suggested code from cengel in this post, I added (what should have been) the graduated circles to my plot with this bit of code:

ggplot() + 
  geom_polygon(data = eth.df, aes(long, lat, group = group, fill = ML1)) + 
  scale_fill_manual(values = c("gray", "yellow", "orange", "red")) + 
  geom_path(data = regions, aes(long, lat, group = group), color = "darkgray") + 
   geom_point(data=branches, aes(x=Lon, y=Lat, size=share, fill=share), shape=21, alpha=0.8) +
  scale_size_continuous(range = c(2, 9), breaks=pretty_breaks(7)) +
  scale_fill_distiller(breaks = pretty_breaks(7)) + 
  coord_equal()

This gives me two errors: Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the existing scale. and Error: Discrete value supplied to continuous scale

Why do these errors occur and how do I fix them so that I can plot the graduated circles on top of my polygon?


EDIT:

Here is my updated code:

#load in required libraries 
library(ggplot2)
library(maptools)
library(rgdal)
library(rgeos)
library(raster)
library(plyr)

#set working directory setwd("D:/Mapping-R/Ethiopia")

#read in data/shapefiles ea.ml1 <- readOGR(dsn = "D:/Mapping-R/Ethiopia", layer = "EA201507_ML1") eth <- readOGR(dsn = "D:/Mapping-R/Ethiopia", layer = "ETH_adm0") regions <- readOGR(dsn = "D:/Mapping-R/Ethiopia", layer = "ETH_adm1") branches <- read.csv("Branches_Africa.csv", header = TRUE)

#remove all unwanted columns from eth shapefile eth <- eth[, -(2:67)]

#clip ethiopia to ml1 background eth.clip1 <- intersect(ea.ml1, eth)

#explicitly identify attribute rows by the .dbf offset, #convert to data frame, making each polygon attribute a point #join points to attributes to fill polygon eth.clip1@data$id <- rownames(eth.clip1@data) eth.f <- fortify(eth.clip1, region = "id") eth.df <- join(eth.f, eth.clip1@data, by = "id")

#converts integers to factors for ggplot eth.df$ML1 <- as.factor(eth.df$ML1)

#create new temp data frame to create ALL ML values for normalizing, add new rows to df temp <- data.frame(long = c(NA, NA, NA), lat = c(NA, NA, NA), order = c(NA, NA, NA), hole = c(FALSE, FALSE, FALSE), piece = c(NA, NA, NA), id = c(NA, NA, NA), group = c(NA, NA, NA), ML1 = c("5", "66", "88"), ID_0 = c(NA, NA, NA)) rownames(temp) <- c("69625", "69626", "69627") eth.df <- rbind(eth.df, temp)

#fortify regions overlay suitable for mapping regions <- fortify(regions)

#deselect branches without shares, select Ethiopia subset (clip), convert to numbers branches <- branches[branches$share != " . ", ] branches <- branches[branches$CO == "ET", ] branches$share <- as.numeric(as.character(branches$share)) ggplot() + geom_polygon(data = eth.df, aes(long, lat, group = group, fill = ML1)) + scale_fill_manual(values = c("gray", "yellow", "orange", "red", "darkred", "#90C3D4", "#76B87E"), name = "IPC Phase of Acute Food Insecurity", labels = c("1: None or Minimal", "2: Stressed", "3: Crisis", "4: Emergency", "5: Catastrophe/Famine", "Lake", "Park/Reserve")) + geom_point(data = branches, aes(Lon, Lat, size = share, color = share), shape = 16) + scale_size_continuous(name = "Share of Country Portfolio", range = c(2, 9), breaks = pretty_breaks(7)) + scale_color_distiller(name = "Share of Country Portfolio", breaks = pretty_breaks(7), direction = 1) + coord_equal()

My graduated circles are properly plotted, but the legend shows up like this: enter image description here

How do I make it so that the graduated circles and color scale are plotted together as they are shown on the map? Is it showing up incorrectly because of the scales running in opposite directions?

Lauren
  • 1,902
  • 5
  • 26
  • 41
  • 2
    I am not sure but you have two fills! in "geom_point(data=branches, aes(x=Lon, y=Lat, size=share, fill=share)" try color=share instead of fill=share, and use scale_colour_distiller(...) instead of scale_fill_distiller(...) – MLavoie Dec 31 '15 at 20:27
  • So it's impossible have fills for both my polygons and points? – Lauren Dec 31 '15 at 20:48
  • 3
    Unless you manually fill (i.e. not map to an aesthetic) that's correct. ggplot2 only has one mapped fill and one mapped color scale per plot. – hrbrmstr Dec 31 '15 at 22:01
  • Oh no! That's super frustrating. So is there a workaround that would allow me to have custom fills for my polygon and points in ggplot2 or should I go back to using base functions to map it? – Lauren Jan 01 '16 at 02:36
  • have you tried what I suggested in my first comment? – MLavoie Jan 03 '16 at 11:50
  • @MLavoie, sorry for the late response, yes, I did try it! For some reason, the legend is not properly printing; the color gradient and graduated circles are plotted separately (but are plotted together correctly). You can take a look at it here, but the plot won't zoom in to show the colors as well (which are above the black circles in my RStudio window). – Lauren Jan 04 '16 at 17:25
  • 1
    if you want the legend together, just give the same name, eg.g scale_fill_manual(name="nameIGave", values = c("gray", "yellow", "orange", "red"))...and scale_color_distiller(name="nameIGave", breaks = pretty_breaks(7)) – MLavoie Jan 04 '16 at 17:31
  • 1
    @MLavoie, I am using scale_size_continuous and scale_color_distiller. I've used the same naming conventions and they are still plotting separately. – Lauren Jan 04 '16 at 19:04
  • maybe you could update your post (with the code you're currently using/testing), without having access to your dataset it's bit hard to help you. – MLavoie Jan 04 '16 at 19:13
  • @MLavoie it's updated! But I'm not sure if I need to make a new question since this has taken sort of a different but related problem. – Lauren Jan 04 '16 at 19:35

1 Answers1

2

I think I got it. I don't have access to your code so I used a made-up example and hopefully you will be able to use it for your own code.

To use for geom_point()

branches <- data.frame(x=c(1, 2.5, 3.5), y=c(3.5, 2, 1), z=c(1, 2, 3))

The example is from the ggplot2 website. To fix your problem, you need to have the same breaks and limits in your scale() argument.

 p <- ggplot(datapoly, aes(x=x, y=y)) + geom_polygon(aes(fill=id, group=id)) + 
      scale_fill_manual(values = c("gray", "yellow", "orange", "red", "darkred", "#90C3D4"), name = "IPC Phase of Acute Food Insecurity", labels = c("1: None or Minimal", "2: Stressed", "3: Crisis", "4: Emergency", "5: Catastrophe/Famine", 
    "Lake")) + 
    geom_point(data = branches, aes(x, y, size = z, color = z), shape = 16) + 
    scale_color_continuous(name = "Share of Country Portfolio", limits=c(1, 3), breaks=seq(1, 3, by=1)) +
    guides(color= guide_legend(), size=guide_legend()) +
    scale_size_continuous(name = "Share of Country Portfolio", limits=c(1, 3), breaks=seq(1, 3, by=1)) + 
    coord_equal() 

enter image description here

the size and color are in the same legend as you wanted!

MLavoie
  • 146
  • 1
  • 9
  • Yes! This did it. My data was at the top of the post, so I guess you didn't see it. It's a little quirky (follow-up question may be forthcoming, hah), but it will do for now! Thank you so much. – Lauren Jan 05 '16 at 18:41
  • related question: how did you save your map image with the "full sized" map + legend? As seen in my image, in order to get all of the legends in the image, I had to stretch the page, but the map image itself stayed small. – Lauren Jan 05 '16 at 18:57
  • I use the regular R console. So from the Quartz2 window, I saved the image as pdf; and then open the pdf with Preview (I used a Mac) and export the image as png image. – MLavoie Jan 05 '16 at 19:01