Choropleth map in ggplot with polygons that have holes

后端 未结 4 522
隐瞒了意图╮
隐瞒了意图╮ 2020-11-30 05:17

I\'m trying to draw a choropleth map of Germany showing poverty rate by state (inspired by this question).

The problem is that some of the states (Berlin, for examp

相关标签:
4条回答
  • 2020-11-30 05:42

    Alternatively you could create that map using rworldmap.

    library(rworldmap)
    library(RColorBrewer)
    library(rgdal)
    
    map <- readOGR(dsn=".", layer="germany3")
    pov <- read.csv("gerpoverty.csv")
    
    #join data to the map
    sPDF <- joinData2Map(pov,nameMap='map',nameJoinIDMap='VARNAME_1',nameJoinColumnData='Id1')
    
    #default map
    #mapPolys(sPDF,nameColumnToPlot='poverty')
    
    colours=brewer.pal(5,"OrRd")
    mapParams <- mapPolys( sPDF
                          ,nameColumnToPlot='poverty'
                          ,catMethod="pretty"
                          ,numCats=5
                          ,colourPalette=colours
                          ,addLegend=FALSE )
    
    
    do.call( addMapLegend, c( mapParams
                              , legendLabels="all"
                              , legendWidth=0.5
                            ))
    
    #to test state names
    #text(pov$x,pov$y,labels=pov$Id1)
    

    German poverty map created using rworldmap

    0 讨论(0)
  • 2020-11-30 05:51

    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()
    

    0 讨论(0)
  • 2020-11-30 05:54

    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.

    0 讨论(0)
  • 2020-11-30 05:54

    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()
    
    0 讨论(0)
提交回复
热议问题