class: center, middle, inverse, title-slide .title[ # Making interactive leaflet maps with R ] .subtitle[ ## Francisco RodrÃguez-Sánchez ] .author[ ###
@frod_san
] --- <style type="text/css"> .remark-slide-content { padding-top: 0px; } .remark-code { font-size: 13px; } .code10 .remark-code { font-size: 10%; } .code20 .remark-code { font-size: 20%; } .code30 .remark-code { font-size: 30%; } .code40 .remark-code { font-size: 40%; } .code50 .remark-code { font-size: 50%; } .code60 .remark-code { font-size: 60%; } .code70 .remark-code { font-size: 70%; } .code80 .remark-code { font-size: 80%; } .code90 .remark-code { font-size: 90%; } </style> --- class: inverse, center, middle # Mapping point data --- ## Palm trees in Sevilla <table> <thead> <tr> <th style="text-align:right;"> X </th> <th style="text-align:right;"> Y </th> <th style="text-align:left;"> species </th> <th style="text-align:right;"> perimeter </th> <th style="text-align:right;"> height </th> </tr> </thead> <tbody> <tr> <td style="text-align:right;"> -5.972411 </td> <td style="text-align:right;"> 37.40811 </td> <td style="text-align:left;"> Washingtonia robusta </td> <td style="text-align:right;"> 119 </td> <td style="text-align:right;"> 12.0 </td> </tr> <tr> <td style="text-align:right;"> -5.951808 </td> <td style="text-align:right;"> 37.37690 </td> <td style="text-align:left;"> Phoenix canariensis </td> <td style="text-align:right;"> 240 </td> <td style="text-align:right;"> 5.0 </td> </tr> <tr> <td style="text-align:right;"> -5.987472 </td> <td style="text-align:right;"> 37.36899 </td> <td style="text-align:left;"> Phoenix dactylifera </td> <td style="text-align:right;"> 131 </td> <td style="text-align:right;"> 7.5 </td> </tr> <tr> <td style="text-align:right;"> -6.006355 </td> <td style="text-align:right;"> 37.37571 </td> <td style="text-align:left;"> Phoenix dactylifera </td> <td style="text-align:right;"> NA </td> <td style="text-align:right;"> NA </td> </tr> <tr> <td style="text-align:right;"> -5.973350 </td> <td style="text-align:right;"> 37.41542 </td> <td style="text-align:left;"> Washingtonia filifera </td> <td style="text-align:right;"> 108 </td> <td style="text-align:right;"> 8.0 </td> </tr> <tr> <td style="text-align:right;"> -6.006485 </td> <td style="text-align:right;"> 37.39652 </td> <td style="text-align:left;"> Chamaerops humilis </td> <td style="text-align:right;"> 45 </td> <td style="text-align:right;"> 2.0 </td> </tr> </tbody> </table> Source: https://opendata.esri.es/datasets/ideSEVILLA::parques-y-jardines-palmera-viario/about --- ## Make interactive map (leaflet) ```r library("leaflet") ``` https://rstudio.github.io/leaflet ([Cheatsheet](https://github.com/rstudio/cheatsheets/blob/main/leaflet.pdf)) --- ## Make interactive map (leaflet) ```r leaflet(palms) %>% addTiles() %>% addMarkers(lng = ~X, lat = ~Y) ```
--- ## Hey those are palm trees! ```r palm.icon <- makeIcon("https://img.icons8.com/ios-glyphs/30/000000/palm-tree.png") leaflet(palms) %>% addTiles() %>% addMarkers(lng = ~X, lat = ~Y, icon = palm.icon) ```
<a href="https://icons8.com/icon/104106/palm-tree">Palm Tree icon by Icons8</a> --- ## Make point clusters ```r leaflet(palms) %>% addTiles() %>% addMarkers(lng = ~X, lat = ~Y, icon = palm.icon, * clusterOptions = markerClusterOptions()) ```
--- ## Maybe just circles? ```r leaflet(palms) %>% addTiles() %>% addCircleMarkers(lng = ~X, lat = ~Y, radius = 5, stroke = FALSE, fillOpacity = 0.7) ```
--- class: inverse, center, middle # Changing basemaps --- ## Default tiles: OpenStreetMap ```r leaflet(palms) %>% * addTiles() %>% addCircleMarkers(lng = ~X, lat = ~Y, radius = 5, stroke = FALSE, fillOpacity = 0.7) ```
--- ## Using other tile providers ```r leaflet(palms) %>% * addProviderTiles(provider = providers$Esri.WorldImagery) %>% addCircleMarkers(lng = ~X, lat = ~Y, radius = 5, stroke = FALSE, fillOpacity = 0.7) ```
--- ## Using other tile providers ```r leaflet(palms) %>% * addProviderTiles(provider = providers$Stamen.Watercolor) %>% addCircleMarkers(lng = ~X, lat = ~Y, radius = 5, stroke = FALSE, fillOpacity = 0.7) ```
--- ## Using other tile providers ```r leaflet(palms) %>% * addProviderTiles(provider = providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, radius = 5, stroke = FALSE, fillOpacity = 0.7) ```
--- ## Using WMS tiles ```r leaflet(palms) %>% * addWMSTiles(baseUrl = "http://www.ign.es/wms-inspire/ign-base", * layers = "IGNBaseTodo-nofondo") %>% addCircleMarkers(lng = ~X, lat = ~Y, radius = 5, stroke = FALSE, fillOpacity = 0.7) ```
--- class: inverse, center, middle # Adding information to points --- ## Point size ~ palm height ```r leaflet(palms) %>% addProviderTiles(providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, * radius = ~height) ```
--- ## Point colour ~ palm height ```r *pal <- colorNumeric(palette = "YlOrRd", domain = palms$height) leaflet(palms) %>% addProviderTiles(providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, radius = 6, fillOpacity = 0.8, * color = ~pal(height)) ```
--- ## Add legend ```r leaflet(palms, height = '400px') %>% addProviderTiles(providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, radius = 6, color = ~pal(height), fillOpacity = 0.7) %>% * addLegend(position = "bottomright", * pal = pal, values = ~height, opacity = 1) ```
--- ## Point colour ~ palm genus (factor) ```r *pal.gen <- colorFactor(palette = "Dark2", domain = palms$genus) leaflet(palms, height = '400px') %>% addProviderTiles(providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, radius = 6, color = ~pal.gen(genus), fillOpacity = 0.7) %>% addLegend(position = "bottomright", pal = pal.gen, values = ~genus, opacity = 1) ```
--- ## Focus on particular area ```r leaflet(palms, height = '400px') %>% addProviderTiles(providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, radius = 8, color = ~pal.gen(genus), fillOpacity = 0.7) %>% addLegend(position = "bottomright", pal = pal.gen, values = ~genus, opacity = 1) %>% * setView(lng = -6, lat = 37.38, zoom = 15) # see also fitBounds ```
--- ## Adding popups ```r leaflet(palms, height = '400px') %>% setView(lng = -6, lat = 37.38, zoom = 15) %>% addProviderTiles(provider = providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, radius = 8, color = ~pal.gen(genus), fillOpacity = 0.7, * popup = ~species) ```
--- class: inverse, middle, center # Advanced popups with `leafpop` https://github.com/r-spatial/leafpop --- ## Show tables with extra information ```r leaflet(palms, height = '400px') %>% setView(lng = -6, lat = 37.38, zoom = 15) %>% addProviderTiles(providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, radius = 8, color = ~pal.gen(genus), fillOpacity = 0.7, * popup = ~leafpop::popupTable(palms, * zcol = c("species", "perimeter", "height"), * row.numbers = FALSE, feature.id = FALSE)) ```
--- ## Popups can show images, videos, anything! ```r leaflet(palms.redux) %>% addProviderTiles(providers$CartoDB.Positron) %>% addCircleMarkers(lng = ~X, lat = ~Y, stroke = FALSE, radius = 8, color = ~pal.gen(genus), fillOpacity = 0.7, * popup = ~leafpop::popupImage(img = palms.redux$pics, * src = "local", embed = TRUE)) ```
--- ## Popups can show images, videos, anything!
--- ## R graphics as popups <img src="data/popup-histog.PNG" width="80%" style="display: block; margin: auto;" /> https://pakillo.github.io/R-Asturias-DataViz-Contest/speedmap.html --- class: inverse, middle, center # Mapping several layers --- ## Show/hide layers (data or basemaps) ```r leaflet(height = '400px') %>% addProviderTiles(providers$CartoDB.Positron) %>% * addCircleMarkers(data = phoenix, group = "Phoenix", lng = ~X, lat = ~Y, stroke = FALSE, radius = 6, color = ~pal.gen(genus), fillOpacity = 0.7) %>% * addCircleMarkers(data = washingtonia, group = "Washingtonia", lng = ~X, lat = ~Y, stroke = FALSE, radius = 6, color = ~pal.gen(genus), fillOpacity = 0.7) %>% * addLayersControl(overlayGroups = c("Phoenix", "Washingtonia"), options = layersControlOptions(collapsed = FALSE)) ```
--- class: inverse, middle, center # Small multiples of leaflet maps with `leafsync` https://github.com/r-spatial/leafsync --- ## Let's build two leaflet maps ```r phoenix.map <- leaflet() %>% addProviderTiles(providers$CartoDB.Positron) %>% * addCircleMarkers(data = phoenix, lng = ~X, lat = ~Y, stroke = FALSE, radius = 6, color = ~pal.gen(genus), fillOpacity = 0.7) ``` ```r washingtonia.map <- leaflet() %>% addProviderTiles(providers$CartoDB.Positron) %>% * addCircleMarkers(data = washingtonia, lng = ~X, lat = ~Y, stroke = FALSE, radius = 6, color = ~pal.gen(genus), fillOpacity = 0.7) ``` --- ## Synchronised small multiples! ```r leafsync::sync(phoenix.map, washingtonia.map) ```
--- class: inverse, middle, center # Mapping other spatial data --- ## Data can be .pull-left[ - Points - Lines - Polygons - Rasters ] .pull-right[ - Matrix/Dataframe - sp - sf - GeoJSON/TopoJSON - raster ] --- ## Sevilla neighbourhoods ```r barrios <- sf::st_read("data/Barrios.shp") ``` ``` ## Reading layer `Barrios' from data source ## `/home/frs/Dropbox/Rcode/myRcode/courses_talks/r-leaflet-maps/data/Barrios.shp' ## using driver `ESRI Shapefile' ## Simple feature collection with 109 features and 7 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: -6.03342 ymin: 37.30045 xmax: -5.818405 ymax: 37.45294 ## Geodetic CRS: WGS 84 ``` ``` ## Simple feature collection with 6 features and 7 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: -6.029277 ymin: 37.31342 xmax: -5.818405 ymax: 37.45294 ## Geodetic CRS: WGS 84 ## FID Barrio DISTRITO DISTRITO_N Superf_Ha ## 1 1 TABLADA 11 Los Remedios 1332.013 ## 2 2 COLORES, ENTREPARQUES 9 Este - Alcosa - Torreblanca 1331.235 ## 3 3 LA BACHILLERA 7 Norte 1327.843 ## 4 4 TORREBLANCA 9 Este - Alcosa - Torreblanca 1335.412 ## 5 5 BELLAVISTA 10 Bellavista - La Palmera 1165.637 ## 6 6 EL GORDILLO 7 Norte 1179.351 ## Shape__Are Shape__Len geometry ## 1 0.001353248 0.1550361 MULTIPOLYGON (((-6.002653 3... ## 2 0.001353701 0.2112231 MULTIPOLYGON (((-5.876799 3... ## 3 0.001350621 0.2632040 MULTIPOLYGON (((-5.954878 3... ## 4 0.001357710 0.2489455 MULTIPOLYGON (((-5.856267 3... ## 5 0.001184084 0.1850147 MULTIPOLYGON (((-5.953938 3... ## 6 0.001199665 0.1871865 MULTIPOLYGON (((-5.935078 3... ``` Source: http://sevilla-idesevilla.opendata.arcgis.com/datasets/38827fc3eac142149801c2efa2a0bdf9_0 --- ## Mapping polygons ```r leaflet(barrios) %>% addTiles() %>% addPolygons(label = ~Barrio) ```
--- ## mapview: quick leaflet maps of any spatial data ```r mapview::mapview(barrios) ```
https://r-spatial.github.io/mapview/ --- ## For big datasets, try https://github.com/r-spatial/leafgl https://symbolixau.github.io/mapdeck/ <img src="data/pointcloud_redux.gif" width="100%" style="display: block; margin: auto;" /> --- class: inverse, middle, center # There are hundreds of [leaflet plugins](https://leafletjs.com/plugins) (not all implemented in R yet) --- ## Add MiniMap ```r leaflet(barrios) %>% addProviderTiles(providers$CartoDB.Positron) %>% addPolygons() %>% * addMiniMap() ```
--- ## Measure distances ```r leaflet(barrios) %>% addProviderTiles(providers$CartoDB.Positron) %>% addPolygons() %>% * addMeasure() ```
--- ## Locate me (using Javascript) ```r leaflet(barrios) %>% addProviderTiles(providers$CartoDB.Positron) %>% addPolygons() %>% * addEasyButton(easyButton( * icon = "fa-crosshairs", title = "Locate Me", * onClick = JS("function(btn, map){ map.locate({setView: true}); }"))) ```
--- ## Search places ```r library("leaflet.extras") leaflet(barrios) %>% addProviderTiles(providers$CartoDB.Positron) %>% addPolygons() %>% * addSearchOSM() ```
--- ## Add reverse search ```r leaflet(barrios) %>% addProviderTiles(providers$CartoDB.Positron) %>% addPolygons() %>% * addReverseSearchOSM() ```
--- ## Animated maps ```r library("leaflet.minicharts") ```
--- ## END ![](CC-BY-NC-SA_logo.png) Slides and source code available at https://github.com/Pakillo/r-leaflet-maps