arcgisgeocode provides access to ArcGIS geocoding services from R. It supports address candidate identification, batch geocoding, reverse geocoding, and autocomplete suggestions.
Install the package from CRAN
# install from CRAN
install.packages("arcgisgeocode")
You can also install the development version from r-universe as a binary for Mac, Windows, or Ubuntu from r-universe like so:
# install from R-universe
install.packages("arcgisgeocode", repos = "https://r-arcgis.r-universe.dev")
Or you can install the package from source which requires Rust to be
available. Follow the rustup
instructions to install Rust and verify your installation is
compatible using rextendr::rust_sitrep()
.
Then install the development version from GitHub:
# install pak if not available
if (!requireNamespace("pak")) install.packages("pak")
# install development version of {arcgisgeocode}
::pak("r-arcgis/arcgisgeocode") pak
By default, the ArcGIS
World Geocoder will be used. This geocoding server provides public
access to the /findAddressCandidates
,
/reverseGeocode
,
and /suggest
endpoints made available via the find_address_candidates()
,
reverse_geocode()
, and suggest_places()
functions respectively.
The batch geocoding endpoint /geocodeAddresses
is available via geocode_addresses()
. However, this
requires the use of an authorization token and may consume credits.
Refer to the ArcGIS World Geocoder official documentation for additional information on use restrictions and licensing. For example, a valid token is required to store the results of geocoding transactions.
Reverse geocoding takes a location and finds the associated address.
[!TIP]
A token is not required to use this function.
library(arcgisgeocode)
# Find addresses from locations
<- reverse_geocode(c(-117.172, 34.052))
rev_res
# preview results
::glimpse(rev_res)
dplyr#> Rows: 1
#> Columns: 23
#> $ match_addr <chr> "600-620 Home Pl, Redlands, California, 92374"
#> $ long_label <chr> "600-620 Home Pl, Redlands, CA, 92374, USA"
#> $ short_label <chr> "600-620 Home Pl"
#> $ addr_type <chr> "StreetAddress"
#> $ type_field <chr> ""
#> $ place_name <chr> ""
#> $ add_num <chr> "608"
#> $ address <chr> "608 Home Pl"
#> $ block <chr> ""
#> $ sector <chr> ""
#> $ neighborhood <chr> "South Redlands"
#> $ district <chr> ""
#> $ city <chr> "Redlands"
#> $ metro_area <chr> ""
#> $ subregion <chr> "San Bernardino County"
#> $ region <chr> "California"
#> $ region_abbr <chr> "CA"
#> $ territory <chr> ""
#> $ postal <chr> "92374"
#> $ postal_ext <chr> ""
#> $ country_name <chr> "United States"
#> $ country_code <chr> "USA"
#> $ geometry <POINT [°]> POINT (-117.172 34.05204)
The find_address_candidates()
function returns geocoding
candidate results. The function is vectorized over the input and will
perform multiple requests in parallel. Each request geocodes one
location at a time.
One or more candidates are returned from the endpoint. You can limit
the number of candidates using the max_locations
argument
(with a maximum of 50).
[!TIP]
A token is not required to use this function.
# Find addresses from address search
<- find_address_candidates(
candidates address = "esri",
address2 = "380 new york street",
city = "redlands",
country_code = "usa",
max_locations = 2
)
::glimpse(candidates[, 1:10])
dplyr#> Rows: 2
#> Columns: 11
#> $ input_id <int> 1, 1
#> $ result_id <int> NA, NA
#> $ loc_name <chr> "World", "World"
#> $ status <chr> "M", "M"
#> $ score <dbl> 100.00, 98.57
#> $ match_addr <chr> "Esri", "380 New York St, Redlands, California, 92373"
#> $ long_label <chr> "Esri, 380 New York St, Redlands, CA, 92373, USA", "380 Ne…
#> $ short_label <chr> "Esri", "380 New York St"
#> $ addr_type <chr> "POI", "PointAddress"
#> $ type_field <chr> "Business Facility", NA
#> $ geometry <POINT [°]> POINT (-117.1957 34.05609), POINT (-117.1948 34.05726)…
Geocoding services can also provide a location suggestion based on a
search term and, optionally, a location or extent. The
suggest_places()
function (/suggest
endpoint)
is intended to be used as part of a client-facing application that
provides autocomplete suggestions.
In this example we create a search extent around a single point and
find suggestions based on the search term "bellwood"
.
[!TIP]
A token is not required to use this function.
# identify a search point as a simple feature column
<- sf::st_sfc(
location ::st_point(c(-84.34, 33.74)),
sfcrs = 4326
)
# buffer and create a bbox object to search within the extent
<- sf::st_bbox(
search_extent ::st_buffer(location, 10)
sf
)
# find suggestions within the bounding box
<- suggest_places(
suggestions "bellwood",
location,search_extent = search_extent
)
suggestions#> # A data frame: 5 × 3
#> text magic_key is_collection
#> * <chr> <chr> <lgl>
#> 1 Bellwood Coffee, 1366 Glenwood Ave SE, Atlanta, GA, 3… dHA9MCN0… FALSE
#> 2 Bellwood, Atlanta, GA, USA dHA9MCN0… FALSE
#> 3 Bellwood Church, Atlanta, GA, USA dHA9MCN0… FALSE
#> 4 Bellwood Yard, Atlanta, GA, USA dHA9MCN0… FALSE
#> 5 Bellwood, IL, USA dHA9NCN0… FALSE
The result is intended to be provided to
find_address_candidates()
to complete the geocoding
process. The column text
contains the address to geocode.
The column magic_key
is a special identifier that makes it
much faster to fetch results. Pass this into the argument
magic_key
.
# get address candidate information
# using the text and the magic key
<- find_address_candidates(
res $text,
suggestionsmagic_key = suggestions$magic_key
)
::glimpse(res[, 1:10])
dplyr#> Rows: 7
#> Columns: 11
#> $ input_id <int> 1, 2, 3, 4, 5, 5, 5
#> $ result_id <int> NA, NA, NA, NA, NA, NA, NA
#> $ loc_name <chr> NA, NA, NA, NA, NA, NA, NA
#> $ status <chr> "M", "M", "M", "M", "T", "T", "T"
#> $ score <dbl> 100, 100, 100, 100, 100, 100, 100
#> $ match_addr <chr> "Bellwood Coffee", "Bellwood, Atlanta, Georgia", "Bellwood…
#> $ long_label <chr> "Bellwood Coffee, 1366 Glenwood Ave SE, Atlanta, GA, 30316…
#> $ short_label <chr> "Bellwood Coffee", "Bellwood", "Bellwood Church", "Bellwoo…
#> $ addr_type <chr> "POI", "Locality", "POI", "POI", "Locality", "Locality", "…
#> $ type_field <chr> "Snacks", "City", "Church", "Building", "City", "City", "C…
#> $ geometry <POINT [°]> POINT (-84.34273 33.74034), POINT (-84.41243 33.77455), PO…
By default, the argument for_storage = FALSE
meaning
that the results of the geocoding operation cannot be persisted. If you
intend to persist the results of the geocoding operation, you must set
for_storage = TRUE
.
To learn more about free and paid geocoding operations refer to the storage parameter documentation.
Many addresses can be geocoded very quickly using the
geocode_addresses()
function which calls the
/geocodeAddresses
endpoint. Note that this function
requires an authorization token. geocode_addresses()
sends
the input addresses in chunks as parallel requests.
Batch geocoding requires a signed in user. Load the {arcgisutils}
to authorize and set your token. This example uses the Geocoding
Test Dataset from the Urban
Institute.
[!TIP]
A token is required to use this function with the World Geocoding Service. It may not be necessary if you are using a private ArcGIS Enterprise service.
library(arcgisutils)
library(arcgisgeocode)
set_arc_token(auth_user())
# Example dataset from the Urban Institute
<- "https://urban-data-catalog.s3.amazonaws.com/drupal-root-live/2020/02/25/geocoding_test_data.csv"
fp
<- readr::read_csv(fp, readr::locale(encoding = "latin1"))
to_geocode
<- to_geocode |>
geocoded ::reframe(
dplyrgeocode_addresses(
address = address,
city = city,
region = state,
postal = zip
)
)
::glimpse(res[, 1:10]) dplyr
{arcgisgeocode}
can be used with other geocoding
services, including custom locators hosted on ArcGIS Online or
Enterprise. For example, we can use the AddressNC geocoding
service available
on ArcGIS Online.
Create a new GeocodeServer
object using
geocode_server()
. This geocoder can be passed into the
geocoder
argument to any of the geocoding functions.
<- geocode_server(
address_nc "https://services.nconemap.gov/secure/rest/services/AddressNC/AddressNC_geocoder/GeocodeServer",
token = NULL
)
<- find_address_candidates(
res address = "rowan coffee",
city = "asheville",
geocoder = address_nc
)
::glimpse(res[, 1:10])
dplyr#> Rows: 2
#> Columns: 11
#> $ input_id <int> 1, 1
#> $ result_id <int> NA, NA
#> $ loc_name <chr> NA, NA
#> $ status <chr> "T", "T"
#> $ score <dbl> 78, 78
#> $ match_addr <chr> "ASHEVILLE", "ASHEVILLE"
#> $ long_label <chr> "ASHEVILLE", "ASHEVILLE"
#> $ short_label <chr> "ASHEVILLE", "ASHEVILLE"
#> $ addr_type <chr> "Locality", "Locality"
#> $ type_field <chr> "City", "City"
#> $ geometry <POINT [US_survey_foot]> POINT (943428.1 681596.4), POINT (948500.3 631973.4)…