Choropleths in R

July 31, 2010

The other day I run into the need of creating choropleths, which are thematic maps where attribute data are displayed using a color scale and look like this:

Chotopleth example

It is a very simple task, provided you have the geo-referenced data, and many packages (such as qGIS) make it a click away. However, I had to create around 300 choropleths and computers were not made for us to click 300 times to perform the same task over and over...

R is a fantastic free software that provides a very powerful graphical support and also has a lot of  great packages other people have contributed, so first I assumed it'd be almost built in. I'm sure it is somewhere, but after 2mins. of googling I realized I'd enjoy more spending time coding it myself (something it looked like a 5-minutes thing) than looking it up on the web, and so I did. After many series of "5 minutes", I did it (and it works). I wasn't really thinking of posting it as it is a very simple function but after some of the pain (and fun) I went trhough to code it, I figured if it saved somebody else time, it'd have been a better invested time.

Big thanks to David Folch for initial idea and support as well as the original source cited below.

Feel free to post any comments or feedback if you've used the function. Thanks in advance.

Sources

Usage

It is a very simple function that assumes you have a shapefile and the attribute data you want to plot are appended to the .dbf that comes with the shapefile. If that is the case, simply pass in the arguments like this:

[sourcecode language="c"]
map <- choropleth(shp, field, png=FALSE, bins=FALSE, bgLayer=FALSE, colPal="Blues", style="hclust", lwd=0.5, title='', sub='', xlab='', ylab='', legend=TRUE)
[/sourcecode]

Simply copy the source code posted below to a file and source it to be able to use the function:

[sourcecode language="c"]
source('/path/to/file.r')
[/sourcecode]

Arguments

Dependencies

  • maptools
  • spatial
  • RColoBrewer
  • classInt
  • Source Code

    [sourcecode language="c" collapse="false"]

    ##################################
    # Choropleth: thematic maps in R #
    ##################################

    # Author: Daniel Arribas-Bel <daniel.arribas.bel@gmail.com>
    # Copyright 2010 by Daniel Arribas-Bel
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.

    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    # GNU General Public License for more details.

    # See: <http://creativecommons.org/licenses/GPL/2.0/> or <http://www.gnu.org/licenses/>

    library(maptools)
    library(spatial)
    library(RColorBrewer)
    library(classInt)

    choropleth <- function(shp, field, png=FALSE, bins=FALSE, bgLayer=FALSE,
    colPal="Blues", style="hclust", lwd=0.5, title='', sub='', xlab='',
    ylab='', legend=TRUE){
    # If not 'bins' -> categorical data
    poly <- readShapeSpatial(shp)
    attach(poly@data, warn.conflicts=FALSE)
    data <- get(field)
    if(bins==FALSE){
    bins <- length(unique(get(field)))
    colCode <- colCoder(poly, field, colPal)
    leyenda <- colCode$legend
    fill <- colCode$paleta
    colCode <- colCode$colVec
    } else {
    colors <- brewer.pal(bins, colPal)
    class = classIntervals(data, bins, style)
    colCode = findColours(class, colors, digits=4)
    leyenda = names(attr(colCode, "table"))
    fill = attr(colCode, "palette")
    }
    detach(poly@data)
    #
    if(png!=FALSE){
    png(png, width=960, height=960, bg="transparent")
    }
    if(bgLayer!=FALSE){
    polyBg <- readShapeSpatial(bgLayer)
    plot(polyBg, lwd=lwd)
    plot(poly, add=TRUE, col=colCode, lwd=lwd)
    } else {
    plot(poly, col=colCode, lwd=lwd)
    }
    title(main=title, sub=sub, xlab=xlab, ylab=ylab)
    if(legend==TRUE){legend("topleft", legend=leyenda, fill=fill, cex=0.75, bty="n")}
    if(png!=FALSE){
    dev.off()
    }
    #"Map created"
    colCode
    }

    colCoder <- function(poly, var, colPal){
    attach(poly@data, warn.conflicts=FALSE)
    uniques <- unique(get(var))
    paleta <- brewer.pal(length(uniques), colPal)
    colVec <- mat.or.vec(length(get(var)), 1)
    for(row in seq(length(get(var)))){
    ind <- which(uniques == get(var)[row])
    colVec[row] <- paleta[ind]
    }
    detach(poly@data)
    res <- list(colVec=colVec, legend=uniques, paleta=paleta)
    res
    }

    [/sourcecode]

    CC-GNU GPL

    This software is licensed under the CC-GNU GPL version 2.0 or later.

    Choropleths in R - July 31, 2010 - Dani Arribas-Bel