Geocode Addresses and Create a Leaflet Map

Summary

This notebook demonstrates how to geocode a set of addresses in a data frame. In this case, the ‘addresses’ consist of city, state, and country (only).

1) Import the Addresses

library(googlesheets4)
library(dplyr)

## Note: this Google Sheet is private, so this will only work if you've already 
## authenticated.
reg_city_state_tbl <- read_sheet(ss = "1vWhj9AcYin2nCnAzG5JpQ7179BQvhZeJpK5b6yz7IrE", 
                             sheet = "Locations") |> 
  rename(city = City, state = `State/Province`, country = Country)
ℹ The googlesheets4 package is using a cached token for 'andlyons@ucdavis.edu'.
Auto-refreshing stale OAuth token.
✔ Reading from "2025-11-07 Spatial Data Fundamentals in R (Responses)".
✔ Range ''Locations''.
head(reg_city_state_tbl)

2) Geocode the addresses

To geocode the addresses we’ll use tidygeocoder:

tidygeocoder supports over ten geocoding services. We’ll use the ArcGIS geocoding service. Even though we aren’t passing an API key, ArcGIS will let us geocode the addresses one at a time.

## Use the ArcGIS Single Address Geocoder
reg_gc_arcgis_tbl <- reg_city_state_tbl |> 
  geocode(city = city,
          state = state,
          country = country,
          method = "arcgis", 
          full_results = TRUE)
Passing 25 addresses to the ArcGIS single address geocoder
Query completed in: 10.4 seconds
reg_gc_arcgis_tbl |> head()


Geocoding Services and Packages

If you have a lot of addresses to geocode, and you have an ArcGIS account, you can batch geocode with the arcgisgeocode package.


3) Convert the geocoded tibble to a sf data frame

The geocoding engine returned a tibble with lon-lat columns. To make the leaflet map, we should first convert the tibble into a sf object:

Linking to GEOS 3.13.1, GDAL 3.10.2, PROJ 9.5.1; sf_use_s2() is TRUE
reg_sf <- reg_gc_arcgis_tbl |> 
  select(city, state, country, long, lat, arcgis_address, score) |> 
  st_as_sf(coords = c("long", "lat"), crs = 4326)

reg_sf


Left column

Right column

4) Create a leaflet object

Finally, we’re ready to create the leaflet object:

library(leaflet)

reg_lflt <- reg_sf |> 
  mutate(popup_html = paste0("<p><strong>", city, "</strong>, ", state, "<br/>", 
                             country, "</p>")) |> 
  leaflet() |> 
  addTiles() |> 
  addCircleMarkers(stroke = FALSE, 
                   radius = 6, 
                   popup = ~popup_html,
                   fillOpacity = 1,
                   clusterOptions = markerClusterOptions(
                     showCoverageOnHover = FALSE, 
                     zoomToBoundsOnClick = TRUE,
                     maxClusterRadius = 10,
                     singleMarkerMode = TRUE))
reg_lflt