Interactive Mapping with Leaflet in R
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Contents
- Introduction
- 1. First Steps
- 3. Exporting your Web Widget
- 3. A closer look on
addTile()
andaddLayersControl()
- Conclusion
Introduction
Leaflet lets you create interactive maps right from the R console. Interactive panning and zooming allows for an explorative view on your pinpointed location. Leaflet provides a simple and fast way to host interactive maps online in R, requiring only 2 lines of code for a basic web map. It is developed by the RStudio team and has therefore a great integration in a workflow with shiny.
The basic usage looks like this:
- Create a map widget
- Add layers of your interest
- Render the map
- … enjoy your beautiful map
1. First Steps
But, where to start? The first step will be the installation of leaflet:
devtools::install_github("rstudio/leaflet")
We have to use devtools because leaflet is not yet on CRAN.
The creation of a basic map-widget is afterwards rather simple:
library(leaflet) your.map <- leaflet() %>% addTiles() your.map # print the map
The function leaflet()
creates a map widget. You can pass your data at this point with the data argument, or add it later on.
For the sake of simplicity, it is very handy to use the pipe operator %>% of the magrittr package (Ctl+Shift+M in R-Studio). Since most of the leaflet functions use the argument data as their first one, this approach makes your code a lot easier to read and you avoid nested bracketted commands. This way we can gradually add elements to our map, one-by-one.
… voilà, your interactive map-widget with the default OpenStreetMap tile layer.
1.2 Adding Data
There are now several ways to illustrate your data:
addControl |
addTiles |
addWMSTiles |
addPopups |
addMarkers |
addCircleMarkers |
addCircles |
addPolylines |
addRectangles |
addPolygons |
addGeoJSON |
With these commands you can add graphics elements and layers to your map. The package provides four options to pass data to the map-widget:
- Data from base R:
- lat/long matrix
- data.frame with lat/long columns
- Data from the sp package:
- any of the spatial classes provided by sp
- Data from maps package:
- any of the maps from the map database
- JSON format:
- add your data in GeoJSON or TopoJSON format via jsonlite
1.2.1 Example
Let’s try adding a hiking trail, one that I plan to hopefully hike in the near future: The Pacific Coast Trail (PCT). The trail spans 2,650 miles (4,265 kilometers) from Mexico to Canada through California, Oregon, and Washington.
First download some data and prepare the layers we want to add:
library(rgdal) library(maps) # Fetch the route of the PCT and convert it into a SpatialLine object url <- "http://hiking.waymarkedtrails.org/en/routebrowser/1225378/gpx" download.file(url, destfile = "pct.gpx", method = "wget") pct <- readOGR("pct.gpx", layer = "tracks") # Import list with shapefiles of the three states the PCT is crossing mapStates <- map("state", fill = TRUE, plot = FALSE, region = c('california', 'oregon', 'washington:main'))
Now we use the appropriate functions to display the layers on the map-widget:
your.map <- leaflet(pct) %>% # Add layer addTiles(urlTemplate = "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png") %>% addPolylines(color="red", popup="PCT") %>% addMarkers(-116.4697, 32.60758, popup = "Campo") %>% addMarkers(-120.7816, 49.06465, popup = "Manning Park, Canada") %>% addPolygons(data=mapStates, fillColor = heat.colors(3, alpha = NULL), stroke = FALSE) %>% # Add legend addLegend(position = 'topright', colors = "red", labels = "PCT", opacity = 0.4, title = 'Legend') your.map
1.4 Useful commands from other spatial R packages
getData
from the raster package. WithgetData
you can retrieve geographic data for anywhere in the world - probably most important will be the possibility to communicate with the spatial database for global administrative areas.geocode
from the ggmap package. Retrieves the coordinates of a spatial search query using Google Maps.
3. Exporting your Web Widget
To my current knowledge there are three ways to export the map-widget from R:
2.1 Shiny
We can render the leaflet object with the following lines of code:
library(shiny) app <- shinyApp( ui <- fluidPage(leafletOutput('myMap')), server <- function(input, output) { map <- your.map output$myMap <- renderLeaflet(map) } ) if (interactive()) print(app)
2.2 RStudio GUI
RStudio offers a “clickable” solution to export the map-widget:
However, these option is only avaible for small layers. The trail of the PCT has over 99,000 vertices and the export fails with:
Stack space overflow: current size 16777216 bytes. Use `+RTS -Ksize -RTS' to increase it. Error: pandoc document conversion failed with error 2
2.3 Rmarkdown
By embedding the leaflet object in a rmarkdown document, which will be rendered into a html:
--- title: "Untitled" output: html_document self_contained: no --- ```{r, echo=F, warning=F, message=F} #load leaflet package for R library(leaflet) library(maps) library(rgdal) url <- "http://hiking.waymarkedtrails.org/en/routebrowser/1225378/gpx" download.file(url, destfile = "pct.gpx", method = "wget") pct <- readOGR("pct.gpx", layer = "tracks") mapStates = map("state", fill = TRUE, plot = FALSE, region = c('california', 'oregon', 'washington:main')) your.map <- leaflet(pct) %>% # Add layer addTiles(urlTemplate = "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png") %>% addPolylines(color="red", , weight = 4, popup="PCT") %>% addMarkers(-116.4697, 32.60758, popup = "Campo") %>% addMarkers(-120.7816, 49.06465, popup = "Manning Park, Canada") %>% addPolygons(data=mapStates, fillColor = heat.colors(3, alpha = NULL), stroke = FALSE) %>% # Add legend addLegend(position = 'topright', colors = "red", labels = "PCT", opacity = 0.4, title = 'Legend') your.map ```
Note that with self_contained: no
you fix the pandoc conversion error from the RStudio GUI.
2.4 Update
I just found this nice funtion from the htmlwidgets package:
saveWidget(widget = your.map, file="your_map.html", selfcontained = FALSE)
Seems to be the smoothest way to export the map-widget, which works even for very big datasets.
3. A closer look on addTile()
and addLayersControl()
For me, one of the fascinating things about the leaflet package was the diverse range of available tiles.
With addTile(urlTemplate = ...)
the integration of any tile is straightforward and lets you compose beautiful maps.
A good resource of available tiles can be found here:
… but wouldn’t it be cool to stack your favorite tiles and chose between them in your map-widget?
Of course it would and the guys from RStudio just implemented these with addLayersControl
.
The function is like the whole package very simple.
You define two groups: i) the baseGroup and ii) the overlayGroup.
Then you pass each individual layer with the parameter group into one of the two groups.
For the baseGroups can only one group at a time be viewed and for the overlayGroups each layer can be individually checked or unchecked.
your.map <- leaflet(pct) %>% # Add tiles as baseGroup addProviderTiles("OpenTopoMap", group = "MapQuestOpen.Aerial") %>% addProviderTiles("MapQuestOpen.Aerial", group = "MapQuestOpen.Aerial") %>% addProviderTiles("OpenMapSurfer.Roads", group = "OpenMapSurfer.Roads") %>% # Add layers as overlayGroup addPolylines(color="red", , weight = 4, popup="PCT", , group = "PCT") %>% addMarkers(-116.4697, 32.60758, popup = "Campo", group="Southern Terminus") %>% addMarkers(-120.7816, 49.06465, popup = "Manning Park, Canada", group="Northern Terminus") %>% hideGroup("Southern Terminus") %>% hideGroup("Northern Terminus") %>% addPolygons(data=mapStates, fillColor = heat.colors(3, alpha = NULL), stroke = FALSE, group = "States") %>% # Layers control addLayersControl( baseGroups = c("MapQuestOpen.Aerial", "OpenTopoMap", "OpenMapSurfer.Roads"), overlayGroups = c("PCT", "Southern Terminus", "Northern Terminus", "States"), options = layersControlOptions(collapsed = FALSE) ) your.map
Conclusion
In my opinion the possibility to embed the map-widget in a Shiny application makes the leaflet package very useful for every kind of spatial analysis. With an app created by shiny in combination with leaflet we can let the user of the app control the parameters of the display of the map, as well as the parameters for any sort of statistical analyse or underlying model. For more details have a look at http://rstudio.github.io/leaflet/shiny.html.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.