19 Leaflet Maps
library(tidyverse)
library(leaflet)
library(sf)
Another interesting approach to make maps is based on the R package "leaflet"
.
The code in this chapter requires the following packages:
library(tidyverse) # for syntactic manipulation of tables
library(leaflet) # for drawing basic geographical maps
library(sf) # provides classes and functions for vector data
and the following table for storms in 1975:
<- filter(storms, year == 1975) storms75
19.1 Introduction
Leaflet is one of the most popular open-source
JavaScript libraries for web-based interactive maps. The good news for R users
is that we also have the homonym R package "leaflet"
that allows us to create
maps directly from the R console, from RStudio, in Shiny applications, and in
source dynamic documents that produce HTML output (e.g. Rmd
, qmd
files).
Extensive documentation for "leaflet"
can be found in RStudio’s
Leaflet for R:
https://rstudio.github.io/leaflet/basemaps.html
19.1.1 Basic World Map
In analogous way to what we’ve done in the last two chapters, let’s start with
a basic map of the world. With "leaflet"
this is straightforward and it is
actually the default map produced by the main function leaflet()
with the
layer addTiles()
leaflet() |>
addTiles()
As you can tell, the way you create a Leaflet map requires 2 basic steps:
Create a map widget by calling
leaflet()
.Add layers (i.e., features) to the map by using layer functions (e.g.
addTiles()
,addMarkers()
,addPolygons()
) to modify the map widget.
The displayed map is an HTML (web-based_ interactive map. Notice that, by
default, addTiles()
uses a map from
OpenStreetMap which is is a free, open
geographic database that provides geospatial data for anybody to use and share.
Zooming
We can zoom in to a certain location of the World by adding another layer
function: setView()
with arguments lng
and lat
for the desired location,
and a zoom
value. For example, we can get a map centered in Miami, Florida:
# view centered at Miami, FL
# value "zoom = 3" found by trail and error
leaflet() |>
addTiles() |>
setView(lng = -80.19, lat = 25.76, zoom = 3)
Since we are using Miami, FL as the point of reference to center our map,
we can also use an addMarkers()
layer with the same set of coordinates to
include a map marker that you can click on and see the text displayed in
the argument popup
:
# view centered at Miami, FL
leaflet() |>
addTiles() |>
setView(lng = -80.19, lat = 25.76, zoom = 3) |>
addMarkers(lng = -80.19, lat = 25.76, popup="Miami")
If you prefer, you can set the view to a different set of coordinates so that
the map is somewhat centered in the middle of the North Atlantic ocean. In
addition, you can use addProviderTiles()
to change the tile from other
map providers. Here’s an example with provider "CartoDB"
# zoom-in in the middle of North Atlantic ocean
leaflet() |>
setView(lng = -50, lat = 30, zoom = 3) |>
addTiles() |>
addProviderTiles(provider = "CartoDB")
And there’s another example with one of my favorite tile providers,
"NASAGIBS.ViirsEarthAtNight2012"
, which gives you a night view of the
Earth:
# zoom-in in the middle of North Atlantic ocean
leaflet() |>
setView(lng = -50, lat = 30, zoom = 3) |>
addTiles() |>
addProviderTiles(provider = "NASAGIBS.ViirsEarthAtNight2012")
To summarize, the creation of Leaflet maps involve the following steps:
start with
leaflet()
.Add layers with functions such as
addTiles()
,addMarkers()
,addPolygons()
, etc to modify the map widget.Repeat step 2 as desired.
Print the map widget to display it.
19.2 Plotting Storms
How do we add the position of storms? By forming a pipeline where we pipe
storms
to leaflet()
, and adding circle markers with addCircleMarkers()
(the equivalent of geom_point()
in "ggplot2"
)
Consider all tropical cyclones back in 1975
First map centered in Miami, Florida
# all tropycal cyclones in 1975
|>
storms75 leaflet() |>
setView(lng = -50, lat = 30, zoom = 2) |>
addProviderTiles(provider = 'CartoDB') |>
addCircleMarkers(
lng = ~long,
lat = ~lat,
radius = 1)
What if we just want to plot the hurricanes? First we get their names, stored in a character vector:
# vector of hurricane names
<- storms75 |>
hurr_names75 filter(wind >= 64) |>
distinct(name) |>
pull(name)
hurr_names75
## [1] "Blanche" "Caroline" "Doris" "Eloise" "Faye" "Gladys"
We can then filter hurricanes:
<- storms75 |>
hurricanes75 filter(name %in% hurr_names75)
And then we pass them to leaflet()
# all hurricanes in 1975
|>
hurricanes75 leaflet() |>
setView(lng = -50, lat = 30, zoom = 2) |>
addProviderTiles(provider = 'CartoDB') |>
addCircleMarkers(
lng = ~long,
lat = ~lat,
radius = 1)
19.2.1 Customizing color palette
As we did with ggplot()
, we can also color the storms in order to distinguish
them:
# If you want to set your own colors manually:
= storms75 |>
count_storms75 distinct(name) |>
nrow()
<- colorFactor(
pal palette = rainbow(n = count_storms75),
domain = storms75$name
)
|>
storms75 leaflet() |>
addProviderTiles('CartoDB') |>
setView(lng = -80.19, lat = 25.76, zoom = 3) |>
addCircleMarkers(
lng = ~long,
lat = ~lat,
radius = 2,
color = ~pal(name))
19.2.2 Adding a Legend
<- rainbow(n = count_storms75)
colores
|>
storms75 leaflet() |>
addProviderTiles('CartoDB') |>
setView(lng = -80.19, lat = 25.76, zoom = 3) |>
addCircleMarkers(
lng = ~long,
lat = ~lat,
radius = 2,
color = ~pal(name)) |>
addLegend(
position = "bottomleft",
color = ~colores,
labels = ~unique(storms75$name),
title = "Storms in 1975",
opacity = 1,
group = "circles"
)