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.
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)
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")
| 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 |
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")
| 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 |
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))
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.
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 | 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 |
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")
| 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 |
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)