Retrieving Open Street Map data using the osmdata package

osmdata is an R package for downloading data from OpenStreetMap (OSM). This tutorial takes you through the steps of retrieving points of interest in defined geographical areas using the osmdata package, and visualising them using the ggmap and ggplot2 packages.

Installing the osmdata package

We can install and load the osmdata package from CRAN as follows

install.packages("osmdata")
library(osmdata)

Exploring the osmdata package

The osmdata package provides spatial data about a wide range of spatial properties and objects across the world. The available_features() function can be used to get the list of recognized features in OSM. A list of the available features can be found in the OSM wiki.

available_features()
##   [1] "4wd_only"                "abandoned"              
##   [3] "abutters"                "access"                 
##   [5] "addr"                    "addr:city"              
##   [7] "addr:conscriptionnumber" "addr:country"           
##   [9] "addr:district"           "addr:flats"             
##  [11] "addr:full"               "addr:hamlet"            
##  [13] "addr:housename"          "addr:housenumber"       
##  [15] "addr:inclusion"          "addr:interpolation"     
##  [17] "addr:place"              "addr:postcode"          
##  [19] "addr:province"           "addr:state"             
##  [21] "addr:street"             "addr:subdistrict"       
##  [23] "addr:suburb"             "admin_level"            
##  [25] "aeroway"                 "agricultural"           
##  [27] "alt_name"                "amenity"                
##  [29] "area"                    "atv"                    
##  [31] "backward"                "barrier"                
##  [33] "basin"                   "bdouble"                
##  [35] "bicycle"                 "bicycle_road"           
##  [37] "biergarten"              "boat"                   
##  [39] "border_type"             "boundary"               
##  [41] "bridge"                  "building"               
##  [43] "building:fireproof"      "building:flats"         
##  [45] "building:levels"         "building:min_level"     
##  [47] "building:soft_storey"    "bus_bay"                
##  [49] "busway"                  "charge"                 
##  [51] "construction"            "covered"                
##  [53] "craft"                   "crossing"               
##  [55] "crossing:island"         "cuisine"                
##  [57] "cutting"                 "cycleway"               
##  [59] "denomination"            "destination"            
##  [61] "diet"                    "direction"              
##  [63] "dispensing"              "disused"                
##  [65] "disused:shop"            "drink"                  
##  [67] "drive_in"                "drive_through"          
##  [69] "ele"                     "electric_bicycle"       
##  [71] "electrified"             "embankment"             
##  [73] "embedded_rails"          "emergency"              
##  [75] "end_date"                "entrance"               
##  [77] "est_width"               "fee"                    
##  [79] "fire_object:type"        "fire_operator"          
##  [81] "fire_rank"               "foot"                   
##  [83] "footway"                 "ford"                   
##  [85] "forestry"                "forward"                
##  [87] "frequency"               "fuel"                   
##  [89] "gauge"                   "golf_cart"              
##  [91] "goods"                   "hazmat"                 
##  [93] "healthcare"              "healthcare:counselling" 
##  [95] "healthcare:speciality"   "height"                 
##  [97] "hgv"                     "highway"                
##  [99] "historic"                "horse"                  
## [101] "ice_road"                "incline"                
## [103] "industrial"              "inline_skates"          
## [105] "inscription"             "internet_access"        
## [107] "junction"                "kerb"                   
## [109] "landuse"                 "lanes"                  
## [111] "lanes:bus"               "lanes:psv"              
## [113] "layer"                   "leaf_cycle"             
## [115] "leaf_type"               "leisure"                
## [117] "lhv"                     "lit"                    
## [119] "location"                "man_made"               
## [121] "maxaxleload"             "maxheight"              
## [123] "maxlength"               "maxspeed"               
## [125] "maxstay"                 "maxweight"              
## [127] "maxwidth"                "military"               
## [129] "minspeed"                "mofa"                   
## [131] "moped"                   "motor_vehicle"          
## [133] "motorboat"               "motorcar"               
## [135] "motorcycle"              "motorroad"              
## [137] "mountain_pass"           "mtb:description"        
## [139] "mtb:scale:imba"          "mtb_scale"              
## [141] "name"                    "name:left"              
## [143] "name:right"              "narrow"                 
## [145] "natural"                 "noexit"                 
## [147] "non_existent_levels"     "note"                   
## [149] "nudism"                  "office"                 
## [151] "official_name"           "old_name"               
## [153] "oneway"                  "opening_hours"          
## [155] "operator"                "organic"                
## [157] "oven"                    "overtaking"             
## [159] "parking:condition"       "parking:lane"           
## [161] "passing_places"          "place"                  
## [163] "power"                   "priority_road"          
## [165] "produce"                 "proposed"               
## [167] "protected_area"          "psv"                    
## [169] "public_transport"        "railway"                
## [171] "railway:preserved"       "railway:track_ref"      
## [173] "recycling_type"          "ref"                    
## [175] "religion"                "residential"            
## [177] "roadtrain"               "route"                  
## [179] "sac_scale"               "service"                
## [181] "service_times"           "shelter_type"           
## [183] "shop"                    "sidewalk"               
## [185] "site"                    "ski"                    
## [187] "smoothness"              "social_facility"        
## [189] "sorting_name"            "speed_pedelec"          
## [191] "start_date"              "step_count"             
## [193] "substation"              "surface"                
## [195] "tactile_paving"          "tank"                   
## [197] "tidal"                   "toilets:wheelchair"     
## [199] "toll"                    "tourism"                
## [201] "tracks"                  "tracktype"              
## [203] "traffic_calming"         "traffic_sign"           
## [205] "trail_visibility"        "trailblazed"            
## [207] "trailblazed:visibility"  "tunnel"                 
## [209] "turn"                    "type"                   
## [211] "usage"                   "vehicle"                
## [213] "vending"                 "voltage"                
## [215] "water"                   "wheelchair"             
## [217] "wholesale"               "width"                  
## [219] "winter_road"             "wood"

The available_tags() function lists out the tags associated with each feature. The tags associated with the feature “amenity” can be retrieved as follows.

available_tags("amenity")
##   [1] "animal_boarding"        "animal_breeding"        "animal_shelter"        
##   [4] "arts_centre"            "atm"                    "baby_hatch"            
##   [7] "baking_oven"            "bank"                   "bar"                   
##  [10] "bbq"                    "bench"                  "bicycle_parking"       
##  [13] "bicycle_rental"         "bicycle_repair_station" "biergarten"            
##  [16] "boat_rental"            "boat_sharing"           "brothel"               
##  [19] "bureau_de_change"       "bus_station"            "cafe"                  
##  [22] "car_rental"             "car_sharing"            "car_wash"              
##  [25] "casino"                 "charging_station"       "childcare"             
##  [28] "cinema"                 "clinic"                 "clock"                 
##  [31] "college"                "community_centre"       "conference_centre"     
##  [34] "courthouse"             "crematorium"            "dentist"               
##  [37] "dive_centre"            "doctors"                "dog_toilet"            
##  [40] "drinking_water"         "driving_school"         "embassy"               
##  [43] "events_venue"           "fast_food"              "ferry_terminal"        
##  [46] "fire_station"           "food_court"             "fountain"              
##  [49] "fuel"                   "funeral_hall"           "gambling"              
##  [52] "give_box"               "grave_yard"             "grit_bin"              
##  [55] "gym"                    "hospital"               "hunting_stand"         
##  [58] "ice_cream"              "internet_cafe"          "kindergarten"          
##  [61] "kitchen"                "kneipp_water_cure"      "language_school"       
##  [64] "library"                "lounger"                "love_hotel"            
##  [67] "marketplace"            "monastery"              "motorcycle_parking"    
##  [70] "music_school"           "nightclub"              "nursing_home"          
##  [73] "parking"                "parking_entrance"       "parking_space"         
##  [76] "pharmacy"               "photo_booth"            "place_of_mourning"     
##  [79] "place_of_worship"       "planetarium"            "police"                
##  [82] "post_box"               "post_depot"             "post_office"           
##  [85] "prison"                 "pub"                    "public_bath"           
##  [88] "public_bookcase"        "public_building"        "ranger_station"        
##  [91] "recycling"              "refugee_site"           "restaurant"            
##  [94] "sanitary_dump_station"  "school"                 "shelter"               
##  [97] "shower"                 "social_centre"          "social_facility"       
## [100] "stripclub"              "studio"                 "swingerclub"           
## [103] "taxi"                   "telephone"              "theatre"               
## [106] "toilets"                "townhall"               "toy_library"           
## [109] "university"             "vehicle_inspection"     "vending_machine"       
## [112] "veterinary"             "waste_basket"           "waste_disposal"        
## [115] "waste_transfer_station" "water_point"            "watering_place"

Creating a query to download data

Defining the bounding box

The first step in creating an osmdata query is defining the geographical area we want to include in the query. This can be done by defining a bounding box that defines a geographical area by its bounding latitudes and longitudes. The osmdata package provides a function getbb() to retrieve the bounding box of a place using its name. We can now create the bounding box of Lagos, the largest city in Nigeria.

lagos_bb <- getbb("Lagos")
lagos_bb
##        min      max
## x 3.234180 3.554180
## y 6.295058 6.615057

Creating an overpass query

The osmdata package retrieves data from the overpass API, which is a read-only API that serves up custom selected parts of the OSM map data. To retrieve the required features of a place (defined by the bounding box), we have to then create an overpass query. This can be easily done using the opq() function of the osmdata package. Here we use the previously defined bounding box of Lagos to create the overpass query

lagos_bb %>%
  opq()
## $bbox
## [1] "6.2950575,3.2341795,6.6150575,3.5541795"
## 
## $prefix
## [1] "[out:xml][timeout:25];\n(\n"
## 
## $suffix
## [1] ");\n(._;>;);\nout body;"
## 
## $features
## NULL
## 
## attr(,"class")
## [1] "list"           "overpass_query"
## attr(,"nodes_only")
## [1] FALSE

Retrieving the osmdata object

Then, the add_osm_feature() function can be used to add the required features to the query, using the features and tags we explored earlier in this tutorial. This query specified in terms of key-value is used to retreive data on hospitals in Lagos.

There are two primary osmdata functions for obtaining data from a query: osmdata_sf() and osmdata_sp(), which return data in simple features (sf) and spatial (sp) formats, respectively. Here, we use the osmdata_sf() function to obtain a simple feature object of the resultant query.

lagos_hospitals <- lagos_bb %>%
  opq() %>%
  add_osm_feature(key = "amenity", value = "hospital") %>%
  osmdata_sf()

Understanding the osmdata object

The osmdata objects will contain the following components

  • A bounding box used in query
  • The call submitted to the overpass API
  • Meta data about the object such as timestamp and version numbers
  • Spatial data - some of which may be empty depending on the type of data retrieved

The following is the osmdata object retrieved by querying the hospitals in Lagos

lagos_hospitals

Note how each component of the osmdata objects is preceded by a $ symbol and some of them are NULL. This is expected, since we queried for hospitals in Lagos, and they are represented using points and polygons only. We can also print out each of these components and explore each of them for a better understanding of them.

# bounding box used in query
lagos_hospitals$bbox
## [1] "6.2950575,3.2341795,6.6150575,3.5541795"
# metadata
lagos_hospitals$meta
## $timestamp
## [1] "[ Thu 5 Jun 2021 03:15:18 ]"
## 
## $OSM_version
## [1] "0.6"
## 
## $overpass_version
## [1] "Overpass API 0.7.56.8 7d656e78"

Note how the Spatial data returned by the query are Simple Feature objects as we requested using theosmdata_sf() function, and how the polygons also contain more details about the hospitals such as their names, websites, wikipedia pages etc. where available.

# osm_points
lagos_hospitals$osm_points
## Simple feature collection with 403 features and 5 fields
## geometry type:  POINT
## dimension:      XY
## bbox:           xmin: 3.250371 ymin: 6.427682 xmax: 3.522714 ymax: 6.610555
## geographic CRS: WGS 84
## First 10 features:
##                osm_id name amenity barrier fixme                  geometry
## 815678325   815678325 <NA>    <NA>    <NA>  <NA> POINT (3.303055 6.461788)
## 928544939   928544939 <NA>    <NA>    <NA>  <NA> POINT (3.361348 6.495705)
## 1209198481 1209198481 <NA>    <NA>    <NA>  <NA> POINT (3.397627 6.447358)
## 1209198504 1209198504 <NA>    <NA>    <NA>  <NA>    POINT (3.397712 6.447)
## 1209198747 1209198747 <NA>    <NA>    <NA>  <NA> POINT (3.397854 6.447192)
## 3024218835 3024218835 <NA>    <NA>    <NA>  <NA> POINT (3.370959 6.511046)
## 3845787945 3845787945 <NA>    <NA>    <NA>  <NA> POINT (3.397503 6.448392)
## 3845787949 3845787949 <NA>    <NA>    <NA>  <NA> POINT (3.397583 6.448494)
## 3845787951 3845787951 <NA>    <NA>    <NA>  <NA>  POINT (3.397146 6.44864)
## 3971452305 3971452305 <NA>    <NA>    <NA>  <NA> POINT (3.386569 6.551142)
# osm_polyogns
lagos_hospitals$osm_polygons
## Simple feature collection with 34 features and 21 fields
## geometry type:  POLYGON
## dimension:      XY
## bbox:           xmin: 3.250371 ymin: 6.427682 xmax: 3.522714 ymax: 6.610555
## geographic CRS: WGS 84
## First 10 features:
##              osm_id                                     name addr.city
## 394119616 394119616                 Gbagada General Hospital      <NA>
## 525043228 525043228     National Orthopaedic Hospital Igbobi      <NA>
## 556508170 556508170         Gold Cross Hospital - Bourdillon     Lagos
## 568367654 568367654          Reddington Hospital - Ikeja GRA      <NA>
## 594743340 594743340                      Reddington Hospital      <NA>
## 595195260 595195260   Eye Foundation Hospital & Laser Centre      <NA>
## 643481485 643481485       St. Kizito Clinic & Maternity Ward      <NA>
## 659370489 659370489        Nigerian Police Hospital - Falomo      <NA>
## 672092174 672092174                   General Hospital Lagos      <NA>
## 704991085 704991085 Lagos State University Teaching Hospital      <NA>
##           addr.housenumber          addr.street alt_name  amenity building
## 394119616             <NA>                 <NA>     <NA> hospital     <NA>
## 525043228             <NA>                 <NA>     <NA> hospital     <NA>
## 556508170              17B      Bourdillon Road     <NA> hospital     <NA>
## 568367654             <NA>                 <NA>     <NA> hospital     <NA>
## 594743340             <NA> Idowu Martins Street     <NA> hospital     <NA>
## 595195260             <NA>                 <NA>     <NA> hospital     <NA>
## 643481485             <NA>                 <NA>     <NA> hospital     <NA>
## 659370489             <NA>                 <NA>     <NA> hospital     <NA>
## 672092174             <NA>                 <NA>     <NA> hospital     <NA>
## 704991085             <NA>                 <NA>     <NA> hospital     <NA>
##           emergency health_facility.type healthcare healthcare.speciality level
## 394119616      <NA>                 <NA>   hospital                  <NA>  <NA>
## 525043228      <NA>                 <NA>   hospital          orthopaedics  <NA>
## 556508170      <NA>                 <NA>   hospital                  <NA>  <NA>
## 568367654      <NA>                 <NA>   hospital                  <NA>  <NA>
## 594743340      <NA>                 <NA>   hospital                  <NA>  <NA>
## 595195260      <NA>                 <NA>   hospital                  <NA>  <NA>
## 643481485      <NA>                 <NA>   hospital                  <NA>  <NA>
## 659370489      <NA>                 <NA>   hospital                  <NA>  <NA>
## 672092174      <NA>                 <NA>   hospital                  <NA>  <NA>
## 704991085      <NA>                 <NA>   hospital                  <NA>  <NA>
##           opening_hours operator short_name source start_date
## 394119616          <NA>     <NA>       <NA>   <NA>       <NA>
## 525043228          <NA>     <NA>      NOHIL   <NA>       <NA>
## 556508170          <NA>     <NA>       <NA>   <NA>       <NA>
## 568367654          <NA>     <NA>       <NA>   <NA>       <NA>
## 594743340          <NA>     <NA>       <NA>   <NA>       <NA>
## 595195260          <NA>     <NA>       <NA>   <NA>       <NA>
## 643481485          <NA>     <NA>       <NA>   <NA>       <NA>
## 659370489          <NA>     <NA>       <NA>   <NA>       <NA>
## 672092174          <NA>     <NA>       <NA>   <NA>       1893
## 704991085          <NA>     <NA>     LASUTH   <NA>       <NA>
##                               website  wikidata
## 394119616                        <NA> Q48743188
## 525043228 http://www.nohlagos.gov.ng/ Q23023017
## 556508170                        <NA>      <NA>
## 568367654                        <NA>      <NA>
## 594743340                        <NA>      <NA>
## 595195260                        <NA>      <NA>
## 643481485                        <NA>      <NA>
## 659370489                        <NA>      <NA>
## 672092174   http://www.ghlagos.org.ng Q19874986
## 704991085                        <NA> Q28449098
##                                             wikipedia
## 394119616                 en:Gbagada General Hospital
## 525043228            en:National Orthopaedic Hospital
## 556508170                                        <NA>
## 568367654                                        <NA>
## 594743340                                        <NA>
## 595195260                                        <NA>
## 643481485                                        <NA>
## 659370489                                        <NA>
## 672092174            en:Lagos Island General Hospital
## 704991085 en:Lagos State University Teaching Hospital
##                                 geometry
## 394119616 POLYGON ((3.387942 6.554221...
## 525043228 POLYGON ((3.368175 6.532734...
## 556508170 POLYGON ((3.436958 6.446001...
## 568367654 POLYGON ((3.356857 6.583489...
## 594743340 POLYGON ((3.420182 6.433274...
## 595195260 POLYGON ((3.456025 6.439484...
## 643481485 POLYGON ((3.505188 6.434465...
## 659370489 POLYGON ((3.42908 6.443328,...
## 672092174 POLYGON ((3.39582 6.448513,...
## 704991085 POLYGON ((3.344492 6.590988...

Visualising queried data with ggplot2 and ggmap

We can visualise the retrieved data about hospitals in Lagos using the ggplot2 package. We can easily visualise simple feature objects using the geom_sf() function of ggplot2.

# install.packages("ggplot2")
library(ggplot2)

ggplot()+
  geom_sf(data = lagos_hospitals$osm_polygons)

While the visualisation above provides useful information about the spread of hospitals in Lagos, it would be useful to plot the locations of hospitals overlayed on a map of Lagos. For this we use the ggmap package. To get a map of Lagos, we use the get_map() function provided by the ggmap package. Here we have used the maptype “roadmap”, but the function allows many more map types which can be found here.

library(ggmap)
lagos_map <- get_map(lagos_bb, maptype = "roadmap")

Then we call ggmap() with the background map retreived map using get_map(), and overlay the spatial data of the hospitals on it using geom_sf(). Note how we have changed the colour and outline line size of the polygons, filled them in and also changed the opacity to introduce some transparency to the polygons. We also set inherit.aes = FALSE to use the aesthetic mappings of the spatial object lagos_hospitals$osm_polygons.

ggmap(lagos_map) +
  geom_sf(data = lagos_hospitals$osm_polygons,
          inherit.aes = FALSE,
          colour = "#08519c",
          fill = "#08306b",
          alpha = .5,
          size = 1) +
  labs(x = "", y = "")

Examples

The following is a complete example of using the osmdata package to retrieve data of hospitals in Lagos and ggmap to visualise them.

#install.packages(c("osmdata", "ggplot2", "ggmap"))
library(osmdata)
library(ggplot2)
library(ggmap)

#creating bounding box for Lagos
lagos_bb <- getbb("Lagos")

# retrieving data of hospitals in Lagos
lagos_hospitals <- lagos_bb %>%
  opq() %>%
  add_osm_feature(key = "amenity", value = "hospital") %>%
  osmdata_sf()

# retrieving map of lagos
lagos_map <- get_map(lagos_bb, maptype = "roadmap")

# visualising map of lagos overlayed by hospitals in lagos
ggmap(lagos_map) +
  geom_sf(data = lagos_hospitals$osm_polygons,
          inherit.aes = FALSE,
          colour = "#08519c",
          fill = "#08306b",
          alpha = .5,
          size = 1) +
  labs(title = "Hospitals in Lagos(Nigeria)",
       x = "Latitude",
       y = "Longitude")

The osmdata package can also be used to download other spatial features such as highways and rivers in Lagos, and overlay them on top of each other using ggplot2 to create a map of Lagos. For this we create multiple queries for each feature as follows.

library(osmdata)
library(ggplot2)

# creating bounding box for Lagos
lagos_bb <- getbb("Lagos")

# retrieving data of streets in Lagos
lagos_streets <- lagos_bb %>%
  opq() %>%
  add_osm_feature("highway", c("motorway", "primary", "secondary", "tertiary")) %>%
  osmdata_sf()

# retrieving data of small streets in Lagos
lagos_small_streets <- lagos_bb %>%
  opq() %>%
  add_osm_feature(key = "highway", value = c("residential", "living_street", "unclassified", "service", "footway")) %>%
  osmdata_sf()

# retrieving data of rivers in Lagos
lagos_rivers <- lagos_bb %>%
  opq() %>%
  add_osm_feature(key = "waterway", value = "river") %>%
  osmdata_sf()

# retrieving data of hospitals in Lagos
lagos_hospitals <- lagos_bb %>%
  opq() %>%
  add_osm_feature("amenity", "hospital") %>%
  osmdata_sf()

Then we use the ggplot2 package to visualise each of these features along with the hospitals in Lagos. Note how we have used different colours, line sizes (thicknesses) and opacities to differentiate among the features.

# visualising all retrieved features over each other to form a map of Lagos
ggplot() +
  geom_sf(data = lagos_streets$osm_lines, inherit.aes = FALSE, color = "#ffbe7f", size = .4, alpha = .8) +
  geom_sf(data = lagos_small_streets$osm_lines, inherit.aes = FALSE, color = "#a6a6a6", size = .2, alpha = .8) +
  geom_sf(data = lagos_rivers$osm_lines, inherit.aes = FALSE, color = "#7fc0ff", size = .8, alpha = .5) +
  geom_sf(data = lagos_hospitals$osm_polygons, inherit.aes = FALSE, colour = "#08519c", fill = "#08306b",alpha = .5, size = 1) +
  coord_sf(xlim = c(3.23, 3.56), ylim = c(6.4,6.629), expand = FALSE) +
  theme_bw() +
  labs(title = "Hospitals in Lagos(Nigeria)",
       x = "Latitude",
       y = "Longitude")

We can also use the leaflet package to visualise an interactive map of the hospitals in Lagos.

#install.packages("leaflet")
library(leaflet)

leaflet() %>% 
  addTiles() %>% 
  addPolygons(data = lagos_hospitals$osm_polygons,
              label = lagos_hospitals$osm_polygons$name)