Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coloring differently adjacent regions on a map with ggplot

Tags:

r

maps

ggplot2

I am trying to make a map of different regions in R with ggplot, where adjacent regions don't have the same color, something aking to what the five color theorem describes.

Regions are groups of californians counties, coded with a number (here the column c20). Using ggplot() and geom_map() with a qualitative scale to color the regions, the closest I get is there:

ggplot() + geom_map(data = data, aes(map_id = geoid, fill = as.factor(c20 %% 12)), 
                  map = county) + expand_limits(x = county$long, y = county$lat) +
coord_map(projection="mercator") +
scale_fill_brewer(palette = "Paired") +
geom_text(data = distcenters, aes(x = clong, y = clat, label = cluster, size = 0.2))

enter image description here

The problem is that adjacent counties from different regions (i.e. with a different number), will sometimes be of the same color. For instance, around Los Angeles, counties from regions 33 & 45 are the same color, and we don't visually differentiate the regions.

Is there a way to do that with ggplot?

like image 471
Erispoe Avatar asked Oct 19 '22 16:10

Erispoe


2 Answers

Try this. It takes a spatial polygons data frame and returns a vector of colours for each element such that no two adjacent polygons have the same colour.

You need to install the spdep package first.

nacol <- function(spdf){
    resample <- function(x, ...) x[sample.int(length(x), ...)]
    nunique <- function(x){unique(x[!is.na(x)])}
    np = nrow(spdf)
    adjl = spdep::poly2nb(spdf)
    cols = rep(NA, np)
    cols[1]=1
    nextColour = 2

    for(k in 2:np){
        adjcolours = nunique(cols[adjl[[k]]])
        if(length(adjcolours)==0){
            cols[k]=resample(cols[!is.na(cols)],1)
        }else{
            avail = setdiff(nunique(cols), nunique(adjcolours))
            if(length(avail)==0){
                cols[k]=nextColour
                nextColour=nextColour+1
            }else{
                cols[k]=resample(avail,size=1)
            }
        }
    }
    return(cols)
}

Test:

  library(spdep)
  example(columbus)
  columbus$C = nacol(columbus)
  plot(columbus,col=columbus$C+1)
like image 129
Spacedman Avatar answered Oct 22 '22 21:10

Spacedman


This is fairly late, but when searching for the same issue, I found a dev package called MapColoring. It does exactly what you asked for.

like image 25
Puki Luki Avatar answered Oct 22 '22 21:10

Puki Luki