1 Lesson overview

Topic: Creating interactive maps with the leaflet package in R.

  • Explain the difference between static and interactive maps.
  • Install and load R packages used for mapping.
  • Create a Leaflet map and set its initial view.
  • Plot locations using latitude and longitude.
  • Add markers, labels, pop-ups, and circle markers.
  • Use color, size, and legends to communicate information.
  • Add tile layers, marker clustering, and polygons.
  • Save an interactive map as an HTML file.

2 1. Introduction to interactive mapping

2.1 1.1 What is a map?

A map is a visual representation of geographical information. Maps help us understand where objects are located and how locations relate to one another.

Examples include:

  • Locations of hospitals and primary health centres.
  • Road networks and transportation routes.
  • Distribution of rainfall, disease cases, or population.
  • Tourist attractions and public services.
  • Disaster-affected regions and flood-prone areas.

2.2 1.2 Static maps versus interactive maps

A static map is a fixed image. Users generally cannot zoom, pan, or click individual locations to reveal more information.

An interactive map allows users to zoom, pan, select markers, explore information, and switch between layers.

2.3 1.3 What is Leaflet?

Leaflet is an open-source JavaScript library for interactive maps. The R package leaflet provides an interface for building these maps directly from R.

Its main capabilities include:

  • Displaying interactive map tiles.
  • Adding markers and pop-ups.
  • Showing circles and polygons.
  • Applying colors according to data values.
  • Adding legends, layer controls, and clustering.
  • Embedding maps in R Markdown, Quarto, and web applications.

Leaflet is useful when we want to combine statistical analysis in R with geographical visualization in a browser.

2.4 1.4 Real-world applications

Consider a public health department studying healthcare accessibility. A Leaflet map could show hospitals, primary health centres, and geographical health indicators. A user could click a facility to view its name and services.

Other applications include crime analysis, environmental monitoring, delivery planning, agriculture, disaster management, and tourism.

3 2. Installing Leaflet and understanding the basics

3.1 2.1 Set up the environment

install.packages("leaflet")
install.packages("dplyr")
install.packages("htmlwidgets")

Load packages in each new R session:

library(leaflet)
library(dplyr)
library(htmlwidgets)
  • install.packages() downloads and installs a package.
  • library() loads an installed package into the current R session.

3.2 2.2 Understand latitude and longitude

A geographical location is often represented using two coordinates:

  • Latitude: angular position north or south of the Equator, from -90 to +90 degrees.
  • Longitude: angular position east or west of the Prime Meridian, from -180 to +180 degrees.

Kochi is approximately at latitude 9.93° N and longitude 76.27° E.

A common source of errors is exchanging these coordinates. In Leaflet, arguments are typically provided as longitude (lng) followed by latitude (lat).

3.3 2.3 Create your first map

leaflet() %>%
  addTiles() %>%
  setView(
    lng = 76.2673,
    lat = 9.9312,
    zoom = 11
  )

3.3.1 Explanation

Function Purpose
leaflet() Creates a map widget.
%>% Passes the previous result into the next operation.
addTiles() Adds a background tile layer.
setView() Sets the initial centre and zoom level.

A smaller zoom value shows a wider region; a larger value shows more local detail.

3.4 2.4 Experiment with zoom levels

leaflet() %>%
  addTiles() %>%
  setView(lng = 76.2673, lat = 9.9312, zoom = 5)

leaflet() %>%
  addTiles() %>%
  setView(lng = 76.2673, lat = 9.9312, zoom = 12)

4 3. Adding markers, labels, and pop-ups

4.1 3.1 Create a dataset

A data frame can store the locations and descriptions we want to visualize.

places <- data.frame(
  name = c(
    "Fort Kochi", "Marine Drive",
    "Lulu Mall", "Kochi Metro"
  ),
  lat = c(9.9658, 9.9816, 10.0261, 9.9726),
  lng = c(76.2423, 76.2760, 76.3084, 76.2999),
  category = c(
    "Heritage", "Boardwalk",
    "Shopping", "Transport"
  )
)

knitr::kable(places, caption = "Illustrative locations for the Leaflet demonstration")
Illustrative locations for the Leaflet demonstration
name lat lng category
Fort Kochi 9.9658 76.2423 Heritage
Marine Drive 9.9816 76.2760 Boardwalk
Lulu Mall 10.0261 76.3084 Shopping
Kochi Metro 9.9726 76.2999 Transport

Each row represents one location:

  • name: location name.
  • lat: latitude.
  • lng: longitude.
  • category: descriptive category.

4.2 3.2 Plot multiple markers

leaflet(data = places) %>%
  addTiles() %>%
  addMarkers(
    lng = ~lng,
    lat = ~lat
  )

The tilde (~) tells Leaflet to use a variable from the supplied data frame. Leaflet plots one marker per row.

4.3 3.3 Add pop-ups and labels

leaflet(data = places) %>%
  addTiles() %>%
  addMarkers(
    lng = ~lng,
    lat = ~lat,
    popup = ~paste0(
      "<b>", name, "</b><br>",
      "Category: ", category
    ),
    label = ~name
  )
  • popup: information displayed when a marker is clicked.
  • label: a short label displayed when the pointer hovers over a marker.
  • paste0(): combines strings without automatically inserting spaces.
  • <b> and <br>: HTML tags for bold text and line breaks inside the pop-up.

4.4 3.4 Customize markers using circles

Circle markers are useful when displaying many locations or numerical measurements.

leaflet(data = places) %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~lng,
    lat = ~lat,
    radius = 7,
    color = "blue",
    fillColor = "lightblue",
    fillOpacity = 0.8,
    popup = ~name
  )
Parameter Meaning
radius Circle size in pixels.
color Border color.
fillColor Interior color.
fillOpacity Transparency of the fill, from 0 to 1.
popup Information displayed on clicking.

4.4.1 Practice:

  1. Increase the circle radius from 7 to 12.
  2. Change the marker color.
  3. Display both the location name and category in the pop-up.

5 4. Visualizing geographical data

The purpose of data visualization is not merely to plot locations. It is to communicate meaningful patterns in the data.

5.1 4.1 Add numerical values to the dataset

health_centres <- data.frame(
  name = c(
    "Centre A", "Centre B", "Centre C",
    "Centre D", "Centre E"
  ),
  lat = c(9.93, 9.95, 9.97, 10.00, 10.02),
  lng = c(76.27, 76.29, 76.25, 76.31, 76.28),
  patients = c(120, 250, 80, 310, 180)
)

knitr::kable(
  health_centres,
  caption = "Synthetic healthcare data"
)
Synthetic healthcare data
name lat lng patients
Centre A 9.93 76.27 120
Centre B 9.95 76.29 250
Centre C 9.97 76.25 80
Centre D 10.00 76.31 310
Centre E 10.02 76.28 180

5.2 4.2 Represent values using circle size

leaflet(health_centres) %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~lng,
    lat = ~lat,
    radius = ~sqrt(patients) / 2,
    color = "darkred",
    fillColor = "tomato",
    fillOpacity = 0.7,
    popup = ~paste(
      name,
      "Patients:", patients,
      sep = "<br>"
    )
  )

The radius increases with the square root of the patient count. This produces a more moderate change in circle size than mapping raw counts directly to radius.

5.3 4.3 Use colors to represent categories

places$color <- ifelse(
  places$category == "Heritage", "red",
  ifelse(
    places$category == "Shopping", "blue",
    ifelse(
      places$category == "Transport", "green",
      "orange"
    )
  )
)

leaflet(places) %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~lng,
    lat = ~lat,
    radius = 8,
    color = ~color,
    fillOpacity = 0.8,
    popup = ~paste(name, category, sep = "<br>")
  )

Assigning colors by category helps users recognize different types of locations. For larger projects, named color palettes are usually easier to maintain than nested ifelse() statements.

5.4 4.4 Add a legend

leaflet(places) %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~lng,
    lat = ~lat,
    radius = 8,
    color = ~color,
    fillOpacity = 0.8,
    popup = ~name
  ) %>%
  addLegend(
    position = "bottomright",
    colors = c("red", "orange", "blue", "green"),
    labels = c(
      "Heritage", "Promenade",
      "Shopping", "Transport"
    ),
    title = "Place Category"
  )

A legend explains the visual encoding. Without one, users may see different colors but not know what they represent.

6 5. Advanced interactive maps

6.1 5.1 Add multiple tile layers

Different tile providers give maps different visual appearances. Provider availability and usage terms should be checked before using them in a public application.

leaflet() %>%
  addTiles(group = "Standard Map") %>%
  addProviderTiles(
    providers$CartoDB.Positron,
    group = "Light Map"
  ) %>%
  addLayersControl(
    baseGroups = c("Standard Map", "Light Map"),
    options = layersControlOptions(
      collapsed = FALSE
    )
  )
  • addProviderTiles() adds a map style from a supported tile provider.
  • group assigns a name to a layer.
  • addLayersControl() creates a control for switching between base layers.

6.2 5.2 Marker clustering

When hundreds of points appear close together, markers may overlap. Clustering groups nearby markers at lower zoom levels.

leaflet(places) %>%
  addTiles() %>%
  addMarkers(
    lng = ~lng,
    lat = ~lat,
    popup = ~name,
    clusterOptions = markerClusterOptions()
  )

This small dataset has only a few locations, so clustering may not be visually obvious. Clustering is more useful when a map contains many points.

6.3 5.4 Save an interactive map as HTML

The map can be displayed in RStudio’s Viewer pane. For sharing, save a Leaflet widget as a standalone HTML file.

library(leaflet)
library(htmlwidgets)

map <- leaflet(places) %>%
  addTiles() %>%
  addMarkers(
    lng = ~lng,
    lat = ~lat,
    popup = ~name
  )

saveWidget(
  map,
  file = "interactive_map.html",
  selfcontained = TRUE
)

The HTML file can be opened in a browser. Depending on the environment and installed dependencies, self-contained export may require additional software such as Pandoc. Background tiles generally still require internet access.

7 6. Hands-on student practical

A district health department wants to visualize five healthcare facilities and the number of patients visiting each facility.

Students will create a map, display facilities, represent patient counts using circle sizes, and add pop-ups.

7.1 Step 1: Prepare the data

facilities <- data.frame(
  facility = c(
    "PHC A", "PHC B", "PHC C",
    "Community Health Centre", "District Hospital"
  ),
  latitude = c(9.93, 9.95, 9.97, 10.00, 10.02),
  longitude = c(76.27, 76.29, 76.25, 76.31, 76.28),
  patients = c(120, 250, 80, 310, 180)
)

knitr::kable(
  facilities,
  caption = "Synthetic facility data"
)
Synthetic facility data
facility latitude longitude patients
PHC A 9.93 76.27 120
PHC B 9.95 76.29 250
PHC C 9.97 76.25 80
Community Health Centre 10.00 76.31 310
District Hospital 10.02 76.28 180

These facility names, coordinates, and patient counts are synthetic teaching data.

7.2 Step 2: Create the interactive map

leaflet(facilities) %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~longitude,
    lat = ~latitude,
    radius = ~sqrt(patients) / 2,
    color = "darkblue",
    fillColor = "skyblue",
    fillOpacity = 0.8,
    popup = ~paste0(
      "<b>", facility, "</b><br>",
      "Patients: ", patients
    ),
    label = ~facility
  ) %>%
  addLegend(
    position = "bottomright",
    colors = "skyblue",
    labels = "Healthcare facility",
    title = "Legend"
  )

7.3 Step 3: Student tasks

  1. Display all five facilities and verify that each row appears as a marker.
  2. Include the facility name and patient count in the pop-up.
  3. Compare circle sizes using sqrt(patients) / 2 and sqrt(patients) / 3.
  4. Change the map’s initial view using setView() and different zoom levels.
  5. Export the map as an HTML file using saveWidget().