{"id":702,"date":"2015-02-03T15:54:06","date_gmt":"2015-02-03T22:54:06","guid":{"rendered":"http:\/\/homepages.uc.edu\/~yaozo\/wordpress\/?p=702"},"modified":"2015-02-03T15:54:06","modified_gmt":"2015-02-03T22:54:06","slug":"using-r-to-quickly-create-an-interactive-online-map-using-the-leafletr-package","status":"publish","type":"post","link":"https:\/\/zhuoyao.net\/index.php\/2015\/02\/03\/using-r-to-quickly-create-an-interactive-online-map-using-the-leafletr-package\/","title":{"rendered":"Using R to quickly create an interactive online map using the leafletR package"},"content":{"rendered":"<article id=\"post-185\" class=\"post-185 post type-post status-publish format-standard hentry category-r category-spatial\">\n<div class=\"entry-content\">\n<p>In a recent post (which you can find <a href=\"http:\/\/zevross.com\/blog\/2014\/04\/03\/interactive-visualization-from-r-to-d3-using-rcharts\/\">here<\/a>) we identified the first publish date for all spatial packages listed in the <a href=\"http:\/\/cran.r-project.org\/web\/views\/Spatial.html\">Analysis of Spatial Data Task View<\/a> on the R website. The most recent of these, published in March 2014, is the <code>leafletR<\/code> 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.<\/p>\n<h2>Introducing Leaflet<\/h2>\n<p>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).<\/p>\n<p>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.<\/p>\n<h2>Get the data<\/h2>\n<p>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.<\/p>\n<p>Here we download and unzip a shapefile from the US Census.<\/p>\n<pre><code class=\"r hljs \"><span class=\"hljs-keyword\">library<\/span>(leafletR)\n<span class=\"hljs-keyword\">library<\/span>(rgdal) <span class=\"hljs-comment\">#for reading\/writing geo files<\/span>\n<span class=\"hljs-keyword\">library<\/span>(rgeos) <span class=\"hljs-comment\">#for simplification<\/span>\n<span class=\"hljs-keyword\">library<\/span>(sp)\n\n<span class=\"hljs-comment\"># note that this file is somewhat big so it might take a couple<\/span>\n<span class=\"hljs-comment\"># of minutes to download<\/span>\nurl&lt;-<span class=\"hljs-string\">\"http:\/\/www2.census.gov\/geo\/tiger\/TIGER2010DP1\/County_2010Census_DP1.zip\"<\/span>\ndownloaddir&lt;-<span class=\"hljs-string\">\"d:\/Leaflet\"<\/span>\ndestname&lt;-<span class=\"hljs-string\">\"tiger.zip\"<\/span>\ndownload.file(url, destname)\nunzip(destname, exdir=downloaddir, junkpaths=<span class=\"hljs-literal\">TRUE<\/span>)\n<\/code><\/pre>\n<h2>A little clipping and projecting<\/h2>\n<p>We&#8217;ve downloaded and unzipped the file. Now we&#8217;re ready to bring the shapefile into R for a little formatting.<\/p>\n<pre><code class=\"r hljs \">filename&lt;-list.files(downloaddir, pattern=<span class=\"hljs-string\">\".shp\"<\/span>, full.names=<span class=\"hljs-literal\">FALSE<\/span>)\nfilename&lt;-gsub(<span class=\"hljs-string\">\".shp\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>, filename)\n\n<span class=\"hljs-comment\"># ----- Read in shapefile (NAD83 coordinate system)<\/span>\n<span class=\"hljs-comment\"># ----- this is a fairly big shapefile and takes 1 minute to read<\/span>\ndat&lt;-readOGR(downloaddir, filename) \n\n<span class=\"hljs-comment\"># ----- Create a subset of New York counties<\/span>\nsubdat&lt;-dat[substring(dat$GEOID10, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">2<\/span>) == <span class=\"hljs-string\">\"36\"<\/span>,]\n\n<span class=\"hljs-comment\"># ----- Transform to EPSG 4326 - WGS84 (required)<\/span>\nsubdat&lt;-spTransform(subdat, CRS(<span class=\"hljs-string\">\"+init=epsg:4326\"<\/span>))\n\n<span class=\"hljs-comment\"># ----- change name of field we will map<\/span>\nnames(subdat)[names(subdat) == <span class=\"hljs-string\">\"DP0010001\"<\/span>]&lt;-<span class=\"hljs-string\">\"Population\"<\/span>\n<\/code><\/pre>\n<h2>Simplify your shapefile if necessary<\/h2>\n<p>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 <code>rgeos<\/code> library to simplify. Note that in a setting where preserving toplogy 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.<\/p>\n<p>Note that another option would be to convert the large GeoJSON to <a href=\"https:\/\/github.com\/mbostock\/topojson\/wiki\">TopoJSON<\/a> using Mike Bostock&#8217;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 <a href=\"https:\/\/github.com\/Leaflet\/Leaflet\/issues\/1284\">issue<\/a> and this <a href=\"http:\/\/bl.ocks.org\/rclark\/5779673\">example<\/a>. You can also see an example of TopoJSON in action, linked with charts using D3, at our site <a href=\"http:\/\/www.zevross.com\/tech\/d3\">here <\/a>.<\/p>\n<pre><code class=\"r hljs \"><span class=\"hljs-comment\"># ----- save the data slot<\/span>\nsubdat_data&lt;-subdat@data[,c(<span class=\"hljs-string\">\"GEOID10\"<\/span>, <span class=\"hljs-string\">\"Population\"<\/span>)]\n\n<span class=\"hljs-comment\"># ----- simplification yields a SpatialPolygons class<\/span>\nsubdat&lt;-gSimplify(subdat,tol=<span class=\"hljs-number\">0.01<\/span>, topologyPreserve=<span class=\"hljs-literal\">TRUE<\/span>)\n\n<span class=\"hljs-comment\"># ----- to write to geojson we need a SpatialPolygonsDataFrame<\/span>\nsubdat&lt;-SpatialPolygonsDataFrame(subdat, data=subdat_data)\n<\/code><\/pre>\n<h2>Ready to play with LeafletR<\/h2>\n<p>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.<\/p>\n<pre><code class=\"r hljs \"><span class=\"hljs-comment\"># ----- Write data to GeoJSON<\/span>\nleafdat&lt;-paste(downloaddir, <span class=\"hljs-string\">\"\/\"<\/span>, filename, <span class=\"hljs-string\">\".geojson\"<\/span>, sep=<span class=\"hljs-string\">\"\"<\/span>) \n\n\nwriteOGR(subdat, leafdat, layer=<span class=\"hljs-string\">\"\"<\/span>, driver=<span class=\"hljs-string\">\"GeoJSON\"<\/span>)\n\n\n<span class=\"hljs-comment\"># ----- Create the cuts<\/span>\ncuts&lt;-round(quantile(subdat$Population, probs = seq(<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0.20<\/span>), na.rm = <span class=\"hljs-literal\">FALSE<\/span>), <span class=\"hljs-number\">0<\/span>)\ncuts[<span class=\"hljs-number\">1<\/span>]&lt;-<span class=\"hljs-number\">0<\/span> <span class=\"hljs-comment\"># ----- for this example make first cut zero<\/span>\n\n\n<span class=\"hljs-comment\"># ----- Fields to include in the popup<\/span>\npopup&lt;-c(<span class=\"hljs-string\">\"GEOID10\"<\/span>, <span class=\"hljs-string\">\"Population\"<\/span>)\n\n\n<span class=\"hljs-comment\"># ----- Gradulated style based on an attribute<\/span>\nsty&lt;-styleGrad(prop=<span class=\"hljs-string\">\"Population\"<\/span>, breaks=cuts, right=<span class=\"hljs-literal\">FALSE<\/span>, style.par=<span class=\"hljs-string\">\"col\"<\/span>,\n               style.val=rev(heat.colors(<span class=\"hljs-number\">6<\/span>)), leg=<span class=\"hljs-string\">\"Population (2010)\"<\/span>, lwd=<span class=\"hljs-number\">1<\/span>)\n\n\n<span class=\"hljs-comment\"># ----- Create the map and load into browser<\/span>\nmap&lt;-leaflet(data=leafdat, dest=downloaddir, style=sty,\n             title=<span class=\"hljs-string\">\"index\"<\/span>, base.map=<span class=\"hljs-string\">\"osm\"<\/span>,\n             incl.data=<span class=\"hljs-literal\">TRUE<\/span>,  popup=popup)\n\n<span class=\"hljs-comment\"># ----- to look at the map you can use this code<\/span>\nbrowseURL(map)\n<\/code><\/pre>\n<h2>Here the final map<\/h2>\n<p>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 <a href=\"http:\/\/bl.ocks.org\/zross\/10469250\">here<\/a>.<\/p>\n<p><iframe loading=\"lazy\" src=\"http:\/\/bl.ocks.org\/zross\/raw\/10469250\/\" width=\"600\" height=\"400\"><\/iframe><\/p>\n<h2>Conclusions<\/h2>\n<p>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.<\/p>\n<\/div>\n<footer class=\"entry-meta entry-footer\"><span class=\"cat-links\">Posted in <a title=\"View all posts in R\" href=\"http:\/\/zevross.com\/blog\/category\/r\/\" rel=\"category tag\">R<\/a>, <a title=\"View all posts in Spatial\" href=\"http:\/\/zevross.com\/blog\/category\/spatial\/\" rel=\"category tag\">Spatial<\/a><\/span><\/footer>\n<\/article>\n<nav class=\"navigation post-navigation\">\n<div class=\"nav-links\"><\/div>\n<\/nav>\n","protected":false},"excerpt":{"rendered":"<p>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&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"class_list":["post-702","post","type-post","status-publish","format-standard","hentry","category-r"],"_links":{"self":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts\/702","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/comments?post=702"}],"version-history":[{"count":0,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts\/702\/revisions"}],"wp:attachment":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/media?parent=702"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/categories?post=702"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/tags?post=702"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}