Access Open Street Map features programmatically with osmdata package in R
OpenStreetMaps is a great source of spatial data. Most common programming languages have packages for downloading data from OSM. In this tutorial we are going to see how to download hosptial features data using R’s osmdata (Padgham et al. 2017) package and plot it using ggplot (Wickham 2016), and interactively using tmap (Tennekes 2018). This requires some knowledge of spatial data structures. We load the package we are going to use in our session.
library(osmdata)
library(tidyverse)
library(patchwork)
library(sf)
library(tmap)
library(ggmap)
require(tmap)
List recognized features in OSM
The osmdata package has a ton of awesome features. It appears that only a fraction of them are available for most cities, and that seems to be primarily those that are related to streets. We’ll focus on those today, but I hope they continue extending this package. The available_features()
function list the features that are in the OSM.
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:postbox"
[19] "addr:postcode" "addr:province"
[21] "addr:state" "addr:street"
[23] "addr:subdistrict" "addr:suburb"
[25] "admin_level" "aeroway"
[27] "agricultural" "alt_name"
[29] "amenity" "area"
[31] "atv" "backward"
[33] "barrier" "basin"
[35] "bdouble" "bicycle"
[37] "bicycle_road" "biergarten"
[39] "boat" "border_type"
[41] "boundary" "bridge"
[43] "building" "building:fireproof"
[45] "building:flats" "building:levels"
[47] "building:min_level" "building:soft_storey"
[49] "bus_bay" "busway"
[51] "charge" "construction"
[53] "construction#Railways" "covered"
[55] "craft" "crossing"
[57] "crossing:island" "cuisine"
[59] "cutting" "cycleway"
[61] "denomination" "destination"
[63] "diet" "diplomatic"
[65] "direction" "dispensing"
[67] "disused" "disused:shop"
[69] "drive_in" "drive_through"
[71] "ele" "electric_bicycle"
[73] "electrified" "embankment"
[75] "embedded_rails" "emergency"
[77] "end_date" "entrance"
[79] "est_width" "fee"
[81] "fire_object:type" "fire_operator"
[83] "fire_rank" "foot"
[85] "footway" "ford"
[87] "forestry" "forward"
[89] "frequency" "fuel"
[91] "gauge" "golf_cart"
[93] "goods" "hazmat"
[95] "healthcare" "healthcare:counselling"
[97] "healthcare:speciality" "height"
[99] "hgv" "highway"
[101] "historic" "horse"
[103] "ice_road" "incline"
[105] "industrial" "inline_skates"
[107] "inscription" "internet_access"
[109] "junction" "kerb"
[111] "landuse" "lanes"
[113] "lanes:bus" "lanes:psv"
[115] "layer" "leaf_cycle"
[117] "leaf_type" "leisure"
[119] "lhv" "lit"
[121] "location" "man_made"
[123] "maxaxleload" "maxheight"
[125] "maxlength" "maxspeed"
[127] "maxstay" "maxweight"
[129] "maxwidth" "military"
[131] "minspeed" "mofa"
[133] "moped" "motor_vehicle"
[135] "motorboat" "motorcar"
[137] "motorcycle" "motorroad"
[139] "mountain_pass" "mtb:description"
[141] "mtb:scale:imba" "mtb_scale"
[143] "name" "name:left"
[145] "name:right" "narrow"
[147] "natural" "noexit"
[149] "non_existent_levels" "note"
[151] "nudism" "office"
[153] "official_name" "old_name"
[155] "oneway" "opening_hours"
[157] "operator" "organic"
[159] "oven" "overtaking"
[161] "parking:condition" "parking:lane"
[163] "passing_places" "place"
[165] "power" "priority_road"
[167] "produce" "proposed"
[169] "protected_area" "psv"
[171] "public_transport" "railway"
[173] "railway:preserved" "railway:track_ref"
[175] "recycling_type" "ref"
[177] "religion" "residential"
[179] "roadtrain" "route"
[181] "sac_scale" "service"
[183] "service_times" "shelter_type"
[185] "shop" "short_name"
[187] "sidewalk" "site"
[189] "ski" "smoothness"
[191] "social_facility" "sorting_name"
[193] "speed_pedelec" "start_date"
[195] "step_count" "substation"
[197] "surface" "tactile_paving"
[199] "tank" "tidal"
[201] "toilets:wheelchair" "toll"
[203] "tourism" "tracks"
[205] "tracktype" "traffic_calming"
[207] "traffic_sign" "trail_visibility"
[209] "trailblazed" "trailblazed:visibility"
[211] "tunnel" "turn"
[213] "type" "usage"
[215] "vehicle" "vending"
[217] "voltage" "water"
[219] "wheelchair" "wholesale"
[221] "width" "winter_road"
[223] "wood"
Once we know the feature, we use avilable_tags
function to obtain all available features of the a particular class feature. FOr example, we want to know the different types of building that are found in
available_tags(feature = "building")
[1] "apartments" "bakehouse"
[3] "barn" "bridge"
[5] "bungalow" "bunker"
[7] "cabin" "carport"
[9] "cathedral" "chapel"
[11] "church" "civic"
[13] "college" "commercial"
[15] "conservatory" "construction"
[17] "container" "cowshed"
[19] "detached" "digester"
[21] "dormitory" "entrance"
[23] "farm" "farm_auxiliary"
[25] "fire_station" "garage"
[27] "garages" "gatehouse"
[29] "ger" "government"
[31] "grandstand" "greenhouse"
[33] "hangar" "hospital"
[35] "hotel" "house"
[37] "houseboat" "hut"
[39] "industrial" "kindergarten"
[41] "kiosk" "library&action=edit&redlink=1"
[43] "military" "monastery"
[45] "mosque" "office"
[47] "parking" "pavilion"
[49] "presbytery" "public"
[51] "religious" "residential"
[53] "retail" "riding_hall"
[55] "roof" "ruins"
[57] "school" "semidetached_house"
[59] "service" "shed"
[61] "shrine" "slurry_tank"
[63] "sports_hall" "stable"
[65] "stadium" "static_caravan"
[67] "sty" "supermarket"
[69] "synagogue" "temple"
[71] "tent" "terrace"
[73] "toilets" "train_station"
[75] "transformer_tower" "transportation"
[77] "tree_house" "university"
[79] "warehouse" "water_tower"
[81] "yes"
Getting the Data
The first step requires downloading data from the OSM api using osmdata. First, I will need to set a bounding box for OSM to search for data with getbb
function. Next, download hosptial in Dar from a building class type with add_osm_feature
function and finally convert the osm dataset into feature class with osmdata_sf
function. The chunk below highlight the key step
## hospital
dar.hosp = getbb(place_name = "dar es salaam") %>%
opq()%>%
add_osm_feature(key = "building", value = "hospital") %>%
osmdata_sf()
hosp = dar.hosp$osm_points
hosp
We then plot the hospital in Dar with tmap, which allows the user to interact with the map
tmap_mode(mode = "view")
tm_shape(shp = hosp)+
tm_bubbles(size = .2)
sometimes you may need a basemap, we can obtain basemap from osmdata as the chunk highlight using a get_map
function from ggplot2 (Wickham 2016).
## basemap
mad_map <- getbb(place_name = "dar es salaam") %>%
get_map(maptype="roadmap",source="osm",color="bw")
Then we can now use ggmap function of ggmap (Kahle and Wickham 2013) to plot a basemap and overlay hospital with geom_sf
function of ggplot2 package and draw a map that show the distribution of hospital in Dar (Figure 1).
ggmap(ggmap = mad_map)+
geom_sf(data = hosp,
inherit.aes = FALSE)+
theme(axis.title = element_blank())