In a recent post (which you can find here) we identified the first publish date for all spatial packages listed in the Analysis of Spatial Data Task View on the R website. The most recent of these, published in March 2014, is the leafletR
package by Christian Graul. We were surprised and impressed that, if you have a GeoJSON file, you can create a Leaflet map with a single line of R code. In this post, though, we demonstrate with an end-to-end example starting with a shapefile.
Introducing Leaflet
Leaflet, an open-source JavaScript library for interactive maps, has proven itself to be a viable alternative to the Google Maps API. Developed by Vladimir Agafonkin, Leaflet is relatively easy to work with and has a lot of momentum in the online mapping world and is currently used by a wide variety of institutions (examples listed on the Leaflet website include Flickr, foursquare, craigslist, Data.gov).
With even a basic web programming background, working with Leaflet is straightforward. The leafletR package, though, is designed to make it particularly easy for R users with limited web programming experience get their maps on the web.
Get the data
For this demonstration we decided to use extremely un-sexy data from the US Census on population by county. We initially load the required libraries, pull the data down from the Census web site and unzip. For this demonstration we will limit to New York State counties.
Here we download and unzip a shapefile from the US Census.
library(leafletR)
library(rgdal) #for reading/writing geo files
library(rgeos) #for simplification
library(sp)
# note that this file is somewhat big so it might take a couple
# of minutes to download
url<-"http://www2.census.gov/geo/tiger/TIGER2010DP1/County_2010Census_DP1.zip"
downloaddir<-"d:/Leaflet"
destname<-"tiger.zip"
download.file(url, destname)
unzip(destname, exdir=downloaddir, junkpaths=TRUE)
A little clipping and projecting
We’ve downloaded and unzipped the file. Now we’re ready to bring the shapefile into R for a little formatting.
filename<-list.files(downloaddir, pattern=".shp", full.names=FALSE)
filename<-gsub(".shp", "", filename)
# ----- Read in shapefile (NAD83 coordinate system)
# ----- this is a fairly big shapefile and takes 1 minute to read
dat<-readOGR(downloaddir, filename)
# ----- Create a subset of New York counties
subdat<-dat[substring(dat$GEOID10, 1, 2) == "36",]
# ----- Transform to EPSG 4326 - WGS84 (required)
subdat<-spTransform(subdat, CRS("+init=epsg:4326"))
# ----- change name of field we will map
names(subdat)[names(subdat) == "DP0010001"]<-"Population"
Simplify your shapefile if necessary
Many shapefiles we work with have significant detail that results in very large GeoJSON files. Without simplifying this county file ends up as a 3mb GeoJSON file so we will use the rgeos
library to simplify. Note that in a setting where preserving topology really matters I would be more likely to use the tools in QGIS or ArcGIS but for this demonstration we will restrict ourselves to R.
Note that another option would be to convert the large GeoJSON to TopoJSON using Mike Bostock’s node.js module. It is easy to use and dramatically reduces the size of GeoJSON files. Working with a TopoJSON file in Leaflet, though, is not as straightforward. For a discussion you can see this issue and this example. You can also see an example of TopoJSON in action, linked with charts using D3, at our site here .
# ----- save the data slot
subdat_data<-subdat@data[,c("GEOID10", "Population")]
# ----- simplification yields a SpatialPolygons class
subdat<-gSimplify(subdat,tol=0.01, topologyPreserve=TRUE)
# ----- to write to geojson we need a SpatialPolygonsDataFrame
subdat<-SpatialPolygonsDataFrame(subdat, data=subdat_data)
Ready to play with LeafletR
With the shapefile in R we are ready to create the GeoJSON file. We will create the cuts we want to map and then create the Leaflet map.
# ----- Write data to GeoJSON
leafdat<-paste(downloaddir, "/", filename, ".geojson", sep="")
writeOGR(subdat, leafdat, layer="", driver="GeoJSON")
# ----- Create the cuts
cuts<-round(quantile(subdat$Population, probs = seq(0, 1, 0.20), na.rm = FALSE), 0)
cuts[1]<-0 # ----- for this example make first cut zero
# ----- Fields to include in the popup
popup<-c("GEOID10", "Population")
# ----- Gradulated style based on an attribute
sty<-styleGrad(prop="Population", breaks=cuts, right=FALSE, style.par="col",
style.val=rev(heat.colors(6)), leg="Population (2010)", lwd=1)
# ----- Create the map and load into browser
map<-leaflet(data=leafdat, dest=downloaddir, style=sty,
title="index", base.map="osm",
incl.data=TRUE, popup=popup)
# ----- to look at the map you can use this code
browseURL(map)
Here the final map
You now have an HTML file called index.html that you can upload. We uploaded this particular file to GitHub as a Gist and you can view it here.
Conclusions
Although this is a post on leafletR you can see that most of the code above is devoted to getting and formatting the data while creating the Leaflet map itself is just a single line of code (or two if you count the styling). The leafletR package is a handy way for R users to create online maps quickly.
It took me a while to figure out how to read back in the geojson data using readOGR, i.e. complete the round trip from writeOGR(subdat, leafdat, layer=””, driver=”GeoJSON”)
So, in case it helps anyone else this is the syntax:
readOGR(dsn = leafdat, layer = “OGRGeoJSON”)
Although you may need to specify the full path, which in this example would be this command:
readOGR(dsn = file.path(downloaddir, leafdat), layer = “OGRGeoJSON”)
The tricky part was that the layer needs to be OGRGeoJSON. Who would have guessed?
Hi Gene, thanks. This is so tricky that I wrote a blog post on this a week ago! Apparently there is work on an rgdal2 package but it is not ready yet.
Hi,
thanks for this post.
I’ve been messing around with leaflet package in R and now that I’ve got my nice map I would like to embed it (with all its interactivities: labels when mouse hover over, popups when you click a marker, etc.) in a post in my wordpress website. I am new to WP too and I can’t find a way to upload this HTML. I know I am going a bit off topic maybe, but if you have a tip that would be more than welcomed. Thanks!