Choropleth map in ggplot with polygons that have holes Choropleth map in ggplot with polygons that have holes r r

Choropleth map in ggplot with polygons that have holes


This is just an expansion on @Ista's answer, which does not require that one knows which states (Berlin, Bremen) need to be rendered last.

This approach takes advantage of the fact that fortify(...) generates a column, hole which identifies whether a group of coordinates are a hole. So this renders all regions (id's) with any holes before (e.g. underneath) the regions without holes.

Many thanks to @Ista, without whose answer I could not have come up with this (believe me, I spent many hours trying...)

ggplot(map.df, aes(x=long, y=lat, group=group)) +  geom_polygon(data=map.df[map.df$id %in% map.df[map.df$hole,]$id,],aes(fill=poverty))+  geom_polygon(data=map.df[!map.df$id %in% map.df[map.df$hole,]$id,],aes(fill=poverty))+  geom_path(colour="grey50")+  scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+  labs(x="",y="")+ theme_bw()+  coord_fixed()


You can plot the island polygons in a separate layer, following the example on the ggplot2 wiki. I've modified your merging steps to make this easier:

mrg.df <- data.frame(id=rownames(map@data),ID_1=map@data$ID_1)mrg.df <- merge(mrg.df,pov, by="ID_1")map.df <- fortify(map)map.df <- merge(map.df,mrg.df, by="id")ggplot(map.df, aes(x=long, y=lat, group=group)) +    geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+    geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, Id1 %in%  c("Berlin", "Bremen")))+    scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+    labs(x="",y="")+ theme_bw()+    coord_fixed()

map of germany

As an unsolicited act of evangelism, I encourage you to consider something like

library(ggmap)qmap("germany", zoom = 6) +    geom_polygon(aes(x=long, y=lat, group=group, fill=poverty),                 color = "grey50", alpha = .7,                 data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+    geom_polygon(aes(x=long, y=lat, group=group, fill=poverty),                 color = "grey50", alpha= .7,                 data =subset(map.df, Id1 %in%  c("Berlin", "Bremen")))+    scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))

to provide context and familiar reference points.


Just to add another small improvement to @Ista's and @jhoward's answers (thanks a lot for your help!).

The modification of @jhoward could be easily wrapped in a small function like this

gghole <- function(fort){        poly <- fort[fort$id %in% fort[fort$hole,]$id,]        hole <- fort[!fort$id %in% fort[fort$hole,]$id,]        out <- list(poly,hole)        names(out) <- c('poly','hole')        return(out)} # input has to be a fortified data.frame

Then, one doesn't need to recall every time how to extract holes info. The code would look like

    ggplot(map.df, aes(x=long, y=lat, group=group)) +            geom_polygon(data=gghole(map.df)[[1]],aes(fill=poverty),colour="grey50")+            geom_polygon(data=gghole(map.df)[[2]],aes(fill=poverty),colour="grey50")+    # (optionally). Call by name    #         geom_polygon(data=gghole(map.df)$poly,aes(fill=poverty),colour="grey50")+    #         geom_polygon(data=gghole(map.df)$hole,aes(fill=poverty),colour="grey50")+            scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+            labs(x="",y="")+ theme_bw()+            coord_fixed()