Introducing the nominatim geocoding package
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
In the never-ending battle for truth, justice and publishing more R packages than Oliver, I whipped out an R package for the OpenStreetMap Nominatim API. It actually hits the MapQuest Nominatim Servers for most of the calls, but the functionality is the same.
The R package lets you:
address_lookup
: Lookup the address of one or multiple OSM objects like node, way or relation.osm_geocode
: Search for places by addressosm_search
: Search for placesosm_search_spatial
: Search for places, returning a list ofSpatialPointsDataFrame
,SpatialLinesDataFrame
or aSpatialPolygonsDataFrame
reverse_geocode_coords
: Reverse geocode based on lat/lonreverse_geocode_osm
: Reverse geocode based on OSM Type & Id
Just like Google Maps, these services are not meant to be your freebie-access to mega-bulk-geocoding. You can and should pay for that. But, when you need a few items geocoded (or want to lookup some interesting things on OSM since it provides special phrases to work with), Nominatim lookups can be just what’s needed.
Let’s say we wanted to see where pubs are in the Seattle metro area. That’s a simple task for nominatim:
# devtools::install_github("hrbrmstr/nominatim") library(nominatim) library(dplyr) sea_pubs <- osm_search("pubs near seattle, wa", limit=20) glimpse(sea_pubs) ## Observations: 20 ## Variables: ## $ place_id (chr) "70336054", "82743439", "11272568", "21478701", "... ## $ licence (chr) "Data © OpenStreetMap contributors, ODbL 1.0. htt... ## $ osm_type (chr) "way", "way", "node", "node", "node", "node", "no... ## $ osm_id (chr) "51460516", "96677583", "1077652159", "2123245933... ## $ lat (dbl) 47.64664, 47.63983, 47.60210, 47.62438, 47.59203,... ## $ lon (dbl) -122.3503, -122.3023, -122.3321, -122.3559, -122.... ## $ display_name (chr) "Nickerson Street Saloon, 318, Nickerson Street, ... ## $ class (chr) "amenity", "amenity", "amenity", "amenity", "amen... ## $ type (chr) "pub", "pub", "pub", "pub", "pub", "pub", "pub", ... ## $ importance (dbl) 0.201, 0.201, 0.201, 0.201, 0.201, 0.201, 0.201, ... ## $ icon (chr) "http://mq-open-search-int-ls03.ihost.aol.com:800... ## $ bbox_left (dbl) 47.64650, 47.63976, 47.60210, 47.62438, 47.59203,... ## $ bbox_top (dbl) 47.64671, 47.63990, 47.60210, 47.62438, 47.59203,... ## $ bbox_right (dbl) -122.3504, -122.3025, -122.3321, -122.3559, -122.... ## $ bbox_bottom (dbl) -122.3502, -122.3022, -122.3321, -122.3559, -122.... |
We can even plot those locations:
library(rgdal) library(ggplot2) library(ggthemes) library(sp) library(DT) # Grab a neighborhood map of Seattle url <- "https://data.seattle.gov/api/file_data/VkU4Er5ow6mlI0loFhjIw6eL6eKEYMefYMm4MGcUakU?filename=Neighborhoods.zip" fil <- "seattle.zip" if (!file.exists(fil)) download.file(url, fil) if (!dir.exists("seattle")) unzip(fil, exdir="seattle") # make it usable sea <- readOGR("seattle/Neighborhoods/WGS84/Neighborhoods.shp", "Neighborhoods") ## OGR data source with driver: ESRI Shapefile ## Source: "seattle/Neighborhoods/WGS84/Neighborhoods.shp", layer: "Neighborhoods" ## with 119 features ## It has 12 fields sea_map <- fortify(sea) # Get the extenes of where the pubs are so we can "zoom in" bnd_box <- bbox(SpatialPoints(as.matrix(sea_pubs[, c("lon", "lat")]))) # plot them gg <- ggplot() gg <- gg + geom_map(data=sea_map, map=sea_map, aes(x=long, y=lat, map_id=id), color="black", fill="#c0c0c0", size=0.25) gg <- gg + geom_point(data=sea_pubs, aes(x=lon, y=lat), color="#ffff33", fill="#ff7f00", shape=21, size=4, alpha=1/2) # decent projection for Seattle-y things and expand the zoom/clip a bit gg <- gg + coord_map("gilbert", xlim=extendrange(bnd_box["lon",], f=0.5), ylim=extendrange(bnd_box["lat",], f=0.5)) gg <- gg + labs(title="Seattle Pubs") gg <- gg + theme_map() gg <- gg + theme(title=element_text(size=16)) gg |
Of course you can geocode:
addrs <- osm_geocode(c("1600 Pennsylvania Ave, Washington, DC.", "1600 Amphitheatre Parkway, Mountain View, CA", "Seattle, Washington")) addrs %>% select(display_name) ## Source: local data frame [3 x 1] ## ## display_name ## 1 Washington, District of Columbia, United States of America ## 2 Mountainview Lane, Huntington Beach, Orange County, California, 92648, Unit ## 3 Seattle, King County, Washington, United States of America addrs %>% select(lat, lon) ## Source: local data frame [3 x 2] ## ## lat lon ## 1 38.89495 -77.03665 ## 2 33.67915 -118.02588 ## 3 47.60383 -122.33006 |
Or, reverse geocode:
# Reverse geocode Canadian embassies # complete list of Canadian embassies here: # http://open.canada.ca/data/en/dataset/6661f0f8-2fb2-46fa-9394-c033d581d531 embassies <- data.frame(lat=c("34.53311", "41.327546", "41.91534", "36.76148", "-13.83282", "40.479094", "-17.820705", "13.09511", "13.09511"), lon=c("69.1835", "19.818698", "12.50891", "3.0166", "-171.76462", "-3.686115", "31.043559", "-59.59998", "-59.59998"), stringsAsFactors=FALSE) emb_coded_coords <- reverse_geocode_coords(embassies$lat, embassies$lon) emb_coded_coords %>% select(display_name) ## Source: local data frame [9 x 1] ## ## display_name ## 1 Embassy of Canada, Ch.R.Wazir Akbar Khan, Kabul, Afghanistan ## 2 Monumenti i Skënderbeut, Skanderbeg Square, Lulishtja Këshilli i Europëes, ## 3 Nomentana/Trieste, Via Nomentana, San Lorenzo, Salario, Municipio Roma II, ## 4 18, Avenue Khalef Mustapha, Ben Aknoun, Daïra Bouzareah, Algiers, Ben aknou ## 5 The Hole in the Wall, Beach Road, Āpia, Samoa ## 6 Torre Espacio, 259 D, Paseo de la Castellana, Fuencarral, Fuencarral-El Par ## 7 Leopold Takawira Street, Avondale West, Harare, Harare Province, 00263, Zim ## 8 Bishop's Court Hill, Bridgetown, Saint Michael, Barbados ## 9 Bishop's Court Hill, Bridgetown, Saint Michael, Barbados |
It can even return Spatial
objects (somewhat experimental):
# stock example search from OSM osm_search_spatial("[bakery]+berlin+wedding", limit=5)[[1]] ## coordinates place_id ## 1 (13.34931, 52.54165) 9039748 ## 2 (13.34838, 52.54125) 2659941153 ## 3 (13.35678, 52.55138) 23586341 ## 4 (13.34985, 52.54158) 7161987 ## 5 (13.35348, 52.5499) 29179742 ## licence ## 1 Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright ## 2 Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright ## 3 Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright ## 4 Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright ## 5 Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright ## osm_type osm_id lat lon ## 1 node 939667448 52.54165 13.34931 ## 2 node 3655549445 52.54125 13.34838 ## 3 node 2299953786 52.55138 13.35678 ## 4 node 762607353 52.54158 13.34985 ## 5 node 2661679367 52.54990 13.35348 ## display_name ## 1 Baguetterie, Föhrer Straße, Brüsseler Kiez, Wedding, Mitte, Berlin, 13353, Germany ## 2 Föhrer Cafe & Backshop, Föhrer Straße, Brüsseler Kiez, Wedding, Mitte, Berlin, 13353, Germany ## 3 Körfez, Amsterdamer Straße, Leopoldkiez, Wedding, Mitte, Berlin, 13347, Germany ## 4 Knusperbäcker, Torfstraße, Brüsseler Kiez, Wedding, Mitte, Berlin, 13353, Germany ## 5 Hofbäckerei, Müllerstraße, Brüsseler Kiez, Wedding, Mitte, Berlin, 13353, Germany ## class type importance ## 1 shop bakery 0.201 ## 2 shop bakery 0.201 ## 3 shop bakery 0.201 ## 4 shop bakery 0.201 ## 5 shop bakery 0.201 ## icon ## 1 http://mq-open-search-int-ls04.ihost.aol.com:8000/nominatim/v1/images/mapicons/shopping_bakery.p.20.png ## 2 http://mq-open-search-int-ls04.ihost.aol.com:8000/nominatim/v1/images/mapicons/shopping_bakery.p.20.png ## 3 http://mq-open-search-int-ls04.ihost.aol.com:8000/nominatim/v1/images/mapicons/shopping_bakery.p.20.png ## 4 http://mq-open-search-int-ls04.ihost.aol.com:8000/nominatim/v1/images/mapicons/shopping_bakery.p.20.png ## 5 http://mq-open-search-int-ls04.ihost.aol.com:8000/nominatim/v1/images/mapicons/shopping_bakery.p.20.png ## bbox_left bbox_top bbox_right bbox_bottom ## 1 52.5416504 52.5416504 13.349306 13.349306 ## 2 52.5412496 52.5412496 13.3483832 13.3483832 ## 3 52.5513806 52.5513806 13.3567785 13.3567785 ## 4 52.54158 52.54158 13.3498507 13.3498507 ## 5 52.5499029 52.5499029 13.3534756 13.3534756 |
The lookup functions are vectorized but there’s a delay built in to avoid slamming the free servers.
Some things on the TODO list are:
- enabling configuration of timeouts
- enabling switching Nominatim API server providers (you can host your own!)
- better
Spatial
support
So, give the code a spin and submit feature requests/issues to github!
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.