Introduction

This tutorial demonstrates how to geocode physical locations using the Bing Maps API. This technique converts a street address into geospatial coordinates, which is useful for calculating drive time and distance between multiple locations, using a location in geospatial analyses, plotting locations on a map, and more. In order to use the Bing Maps API, you must first request create a Bing Maps Developer account and then generate an API Key.

Install and load libraries

This step uses the pacman package to install and load all of the packages for this tutorial.

# Use pacman package to load packages used for exercise
library(pacman)

p_load(dplyr, kableExtra, RCurl, rjson, leaflet)

Part I: Geocode Street Addresses

Step 1: Load data

The typical use of geocoding is to convert street addresses to latitude and longitude coordinates. For example, below are the street addresses of the 12 UPMC hospitals located in Southwestern Pennsylvania. Their addresses were taken from this public page on UPMC’s website.

# Load Southwest PA region UPMC hospital locations
upmc_hospitals <- read.csv("./data/UPMC Locations.csv")

# Display data
upmc_hospitals %>%
  kbl(caption = "UPMC Hospitals in Southwest PA", 
      align = "r", row.names = FALSE) %>%
  kable_minimal("hover")
UPMC Hospitals in Southwest PA
Location Address
UPMC Children’s Hospital of Pittsburgh 4401 Penn Ave, Pittsburgh, PA 15224
UPMC East 2775 Mosside Blvd, Monroeville, PA 15146
UPMC Magee-Womens Hospital 300 Halket St, Pittsburgh, PA 15146
UPMC McKeesport 1500 5th Ave, McKeesport, PA 15132
UPMC Mercy 1400 Locust St, Pittsburgh, PA 15219
UPMC Montefiore 3459 Fifth Ave, Pittsburgh, PA 15213
UPMC Passavant - Cranberry 1 St. Francis Way, Craberry Township, PA 16066
UPMC Passavant - McCandless 9100 Babcock Blvd, Pittsburgh, PA 15237
UPMC Presbyterian 200 Lothrop St, Pittsburgh, PA 15213
UPMC Shadyside 5230 Centre Ave, Pittsburgh, PA 15232
UPMC St. Margaret 815 Freeport Rd, Pittsburgh, PA 15215
UPMC Western Psychiatric Hospital 3811 O’Hara St, Pittsburgh, PA 15213

Step 2: Geocode UPMC Hospitals

The code below takes each of the UPMC Hospital addresses from step 1 above, stored in the field upmc_hospitals$Address, and the user’s Bing Maps API key to request the coordinates from the Bing Maps API. If coordinates are found, then they will be added to the corresponding address in the new fields “Latitude” and “Longitude”; otherwise, if no match is found, then “NA” will be assigned for the two coordinate fields of that address.

# Store Bing Maps API key
BingMapsKey <- "[insert your API key here]"

# Loop through each hospital address and add geospatial coordinates
for(i in 1:nrow(upmc_hospitals)){

  url <- URLencode(paste0("http://dev.virtualearth.net/REST/v1/Locations?q=",
                          upmc_hospitals$Address[i],"&maxResults=1&key=",BingMapsKey))
  json <- fromJSON(getURL(url), simplify = FALSE)
  
  if (json$resourceSets[[1]]$estimatedTotal > 0) {
    lat <- json$resourceSets[[1]]$resources[[1]]$point$coordinates[[1]]
    lon <- json$resourceSets[[1]]$resources[[1]]$point$coordinates[[2]]
  }  else {
    lat <- lon <- NA
  }

  upmc_hospitals$Latitude[i] <- lat
  upmc_hospitals$Longitude[i] <- lon
}

# Display UPMC Hospital data for Southwest PA Region with geocoded location
upmc_hospitals %>%
  kbl(caption = "UPMC Hospitals in Southwest PA with Geocoded Coordinates", 
      align = "r", row.names = FALSE) %>%
  kable_minimal("hover")
UPMC Hospitals in Southwest PA with Geocoded Coordinates
Location Address Latitude Longitude
UPMC Children’s Hospital of Pittsburgh 4401 Penn Ave, Pittsburgh, PA 15224 40.46657 -79.95315
UPMC East 2775 Mosside Blvd, Monroeville, PA 15146 40.43666 -79.76028
UPMC Magee-Womens Hospital 300 Halket St, Pittsburgh, PA 15146 40.43681 -79.96070
UPMC McKeesport 1500 5th Ave, McKeesport, PA 15132 40.35162 -79.84907
UPMC Mercy 1400 Locust St, Pittsburgh, PA 15219 40.43623 -79.98560
UPMC Montefiore 3459 Fifth Ave, Pittsburgh, PA 15213 40.44058 -79.96178
UPMC Passavant - Cranberry 1 St. Francis Way, Craberry Township, PA 16066 40.68328 -80.09830
UPMC Passavant - McCandless 9100 Babcock Blvd, Pittsburgh, PA 15237 40.57290 -80.01395
UPMC Presbyterian 200 Lothrop St, Pittsburgh, PA 15213 40.44241 -79.96029
UPMC Shadyside 5230 Centre Ave, Pittsburgh, PA 15232 40.45428 -79.93960
UPMC St. Margaret 815 Freeport Rd, Pittsburgh, PA 15215 40.48925 -79.89633
UPMC Western Psychiatric Hospital 3811 O’Hara St, Pittsburgh, PA 15213 40.44373 -79.95988

Step 3: Plot UPMC Hospital Locations

Below is a leaflet map with each of the UPMC hospitals plotted by their geocoded coordinates.

# URL for public use icon for hospitals:
icon <- paste0("https://icons.iconarchive.com/icons/google/",
        "noto-emoji-travel-places/256/42491-hospital-icon.png")

# Plot points at each of the UMPC Hospital locations
leaflet() %>% 
  addProviderTiles("CartoDB.Positron", group="Greyscale") %>% 
  addMarkers(upmc_hospitals$Longitude, upmc_hospitals$Latitude,
             icon = list(
              iconUrl = icon,
              iconSize = c(35, 35)),
             popup = paste0("<b>",upmc_hospitals$Location,
             "</b><br>",upmc_hospitals$Address))

Part II: Geocode ZIP Codes

The Bing Maps API can also be used to provide coordinates for more broad geographic locations, like ZIP codes. The code below demonstrates how to use the Bing Maps API to find geospatial coordinates for a street address that is within the provided ZIP code. This is a substitute for finding a centroid for that same ZIP code, and ensures that the returned coordinates can be used for calculations that include navigation from that point.

Step 1: Load list of ZIP Codes

All ZIP Codes in Allegheny County, PA from the 2021 Q4 ZIP code to county crosswalk provided by the US Department of Housing and Urban Development.

# Load List of Allegheny County, PA ZIP Codes from HUD
allegheny_zips <- read.csv("./data/ZIP_COUNTY_122021.csv",
  colClasses = (zip = "character")) %>%
  filter(county == 42003) %>%
  group_by(zip) %>%
  top_n(1, res_ratio) %>%
  mutate(City = gsub("(?<=\\b)([a-z])", "\\U\\1",
         tolower(usps_zip_pref_city), perl=TRUE)) %>%
  rename(ZIP = zip,
         County = county,
         State = usps_zip_pref_state) %>%
  select(ZIP, City, County, State) %>%
  arrange(ZIP)

# Display first 10 rows of ZIP code data
allegheny_zips[1:10,] %>%
  kbl(caption = "ZIP Codes in Allegheny County", 
      align = "r", row.names = FALSE) %>%
  kable_minimal("hover")
ZIP Codes in Allegheny County
ZIP City County State
15001 Aliquippa 42003 PA
15003 Ambridge 42003 PA
15005 Baden 42003 PA
15006 Bairdford 42003 PA
15007 Bakerstown 42003 PA
15012 Belle Vernon 42003 PA
15014 Brackenridge 42003 PA
15015 Bradfordwoods 42003 PA
15017 Bridgeville 42003 PA
15018 Buena Vista 42003 PA

Step 2: Geocode ZIP Codes

The code below finds coordinates for a street address in each of the ZIP codes loaded in step 1 above. If no match is found, then “NA” will be assigned for the two coordinate fields for that ZIP code.

# Loop through each Allegehny County ZIP Code to find geospatial coordinates for a street address near the center of that ZIP code
for(i in 1:nrow(allegheny_zips)){

  url <- URLencode(paste0("http://dev.virtualearth.net/REST/v1/Locations?q=",
                          allegheny_zips$ZIP[i],"&maxResults=1&key=",BingMapsKey))
  json <- fromJSON(getURL(url), simplify = FALSE)
  
  if (json$resourceSets[[1]]$estimatedTotal > 0) {
    lat <- json$resourceSets[[1]]$resources[[1]]$point$coordinates[[1]]
    lon <- json$resourceSets[[1]]$resources[[1]]$point$coordinates[[2]]
  }  else {
    lat <- lon <- NA
  }

  allegheny_zips$Latitude[i] <- lat
  allegheny_zips$Longitude[i] <- lon
}

# Display first 10 rows of ZIP code data with geocoded location
allegheny_zips[1:10,] %>%
  kbl(caption = "Allegheny County ZIP Codes with Geocoded Coordinates", 
      align = "r", row.names = FALSE) %>%
  kable_minimal("hover")
Allegheny County ZIP Codes with Geocoded Coordinates
ZIP City County State Latitude Longitude
15001 Aliquippa 42003 PA 40.60068 -80.28081
15003 Ambridge 42003 PA 40.59342 -80.22189
15005 Baden 42003 PA 40.63871 -80.19928
15006 Bairdford 42003 PA 40.63161 -79.88007
15007 Bakerstown 42003 PA 40.65100 -79.93566
15012 Belle Vernon 42003 PA 40.15799 -79.81738
15014 Brackenridge 42003 PA 40.60984 -79.74207
15015 Bradfordwoods 42003 PA 40.63476 -80.08659
15017 Bridgeville 42003 PA 40.34584 -80.11489
15018 Buena Vista 42003 PA 40.26614 -79.79324

Step 3: Plot ZIP Code Locations

Below is a leaflet map with a circle over the geocoded coordinates for each of the ZIP codes in Allehgeny County, PA.

# Plot points at each of the UMPC Hospital locations
leaflet() %>% 
  addProviderTiles("CartoDB.Positron", group="Greyscale") %>% 
  addCircles(allegheny_zips$Longitude, allegheny_zips$Latitude,
             popup = paste0("<b>",allegheny_zips$ZIP,
             "</b><br>",allegheny_zips$City),
             radius = 1000, opacity = .35)