Hasta acá estuvimos trabajando con datos que fueron descargados de portales open data oficiales de diferentes Ciudades del mundo, pero esa no es la única fuente de información que existe para analizar Ciudades! Por suerte hay varios repositorios online de donde podemos descargarnos información georreferenciada muy interesante, cómo por ejemplo: OpenStreetMap (OSM, https://www.openstreetmap.org/)
¿Qué es y cómo funciona OpenStreerMap?
OSM es una plataforma creada por una gran comunidad de colaboradores que aportan datos geoespaciales de muchas Ciudades del mundo (calles, rutas, restaurants, museos, hospitales, escuelas, etc.) y los mantienen actualizados. Esta información es consumida por miles de sitios web y aplicaciones ya que puede ser utilizada libremente para cualquier propósito siempre y cuando se respeten los derechos de autor y licencia. Se puede consultar más información en la wiki de OSM.
Por suerte, en R existe un paquete llamado osmdata que nos permitirá conectarnos directamente a OSM y descargarnos toda la información que necesitemos. Así que, comencemos activando las ya conocidas tidyverse, sf y ggmap e instalemos y activemos osmdata:
#install.packages("tidyverse")
library(tidyverse)
#install.packages("sf")
library(sf)
#install.packages("ggmap")
library(ggmap)
#install.packages("osmdata")
library(osmdata)
Cualquier duda sobre el paquete osmdata pueden consultarlo en su documentación oficial.
¿QUÉ INFORMACIÓN PODEMOS BUSCAR?
Antes de comenzar a descargar información, utilicemos unos minutos para analizar y conocer que información tenemos disponible. En este este link podrán encontrar una lista detallada de las categorías y tipo de elementos que existen en OSM, pero si quisiésemos también podríamos hacer algunas consultas desde RStudio con available_features() y available_tags(). La primer función nos permitirá obtener el encabezado de la información que contiene la base de datos que nos podemos descargar:
available_features()
## [1] "4wd_only" "abandoned"
## [3] "abutters" "access"
## [5] "addr" "addr:city"
## [7] "addr:conscriptionnumber" "addr:country"
## [9] "addr:county" "addr:district"
## [11] "addr:flats" "addr:full"
## [13] "addr:hamlet" "addr:housename"
## [15] "addr:housenumber" "addr:inclusion"
## [17] "addr:interpolation" "addr:place"
## [19] "addr:postbox" "addr:postcode"
## [21] "addr:province" "addr:state"
## [23] "addr:street" "addr:subdistrict"
## [25] "addr:suburb" "addr:unit"
## [27] "admin_level" "aeroway"
## [29] "agricultural" "alt_name"
## [31] "amenity" "area"
## [33] "atv" "backward"
## [35] "barrier" "basin"
## [37] "bdouble" "bicycle"
## [39] "bicycle_road" "biergarten"
## [41] "boat" "border_type"
## [43] "boundary" "bridge"
## [45] "building" "building:colour"
## [47] "building:fireproof" "building:flats"
## [49] "building:levels" "building:material"
## [51] "building:min_level" "building:part"
## [53] "building:soft_storey" "bus_bay"
## [55] "busway" "castle_type"
## [57] "change" "charge"
## [59] "construction" "construction#Railways"
## [61] "covered" "craft"
## [63] "crossing" "crossing:island"
## [65] "cuisine" "cutting"
## [67] "cycleway" "denomination"
## [69] "destination" "diet"
## [71] "diplomatic" "direction"
## [73] "dispensing" "disused"
## [75] "disused:shop" "drive_in"
## [77] "drive_through" "ele"
## [79] "electric_bicycle" "electrified"
## [81] "embankment" "embedded_rails"
## [83] "emergency" "end_date"
## [85] "entrance" "est_width"
## [87] "fee" "fire_object:type"
## [89] "fire_operator" "fire_rank"
## [91] "foot" "footway"
## [93] "ford" "forestry"
## [95] "forward" "frequency"
## [97] "fuel" "gauge"
## [99] "golf_cart" "goods"
## [101] "hazmat" "healthcare"
## [103] "healthcare:counselling" "healthcare:speciality"
## [105] "height" "hgv"
## [107] "highway" "historic"
## [109] "horse" "ice_road"
## [111] "incline" "industrial"
## [113] "inline_skates" "inscription"
## [115] "internet_access" "junction"
## [117] "kerb" "landuse"
## [119] "lanes" "lanes:bus"
## [121] "lanes:psv" "layer"
## [123] "leaf_cycle" "leaf_type"
## [125] "leisure" "lhv"
## [127] "lit" "location"
## [129] "man_made" "maxaxleload"
## [131] "maxheight" "maxlength"
## [133] "maxspeed" "maxstay"
## [135] "maxweight" "maxwidth"
## [137] "military" "minspeed"
## [139] "mofa" "moped"
## [141] "motor_vehicle" "motorboat"
## [143] "motorcar" "motorcycle"
## [145] "motorroad" "mountain_pass"
## [147] "mtb:description" "mtb:scale:imba"
## [149] "mtb_scale" "name"
## [151] "name:left" "name:right"
## [153] "narrow" "natural"
## [155] "noexit" "non_existent_levels"
## [157] "note" "nudism"
## [159] "office" "official_name"
## [161] "old_name" "oneway"
## [163] "opening_hours" "operator"
## [165] "organic" "oven"
## [167] "overtaking" "parking:condition"
## [169] "parking:lane" "passing_places"
## [171] "place" "power"
## [173] "priority_road" "produce"
## [175] "proposed" "protected_area"
## [177] "psv" "public_transport"
## [179] "railway" "railway:preserved"
## [181] "railway:track_ref" "recycling_type"
## [183] "ref" "religion"
## [185] "residential" "roadtrain"
## [187] "route" "sac_scale"
## [189] "service" "service_times"
## [191] "shelter_type" "shop"
## [193] "short_name" "sidewalk"
## [195] "site" "ski"
## [197] "smoothness" "social_facility"
## [199] "sorting_name" "speed_pedelec"
## [201] "start_date" "step_count"
## [203] "substation" "surface"
## [205] "tactile_paving" "tank"
## [207] "tidal" "toilets:wheelchair"
## [209] "toll" "tourism"
## [211] "tracks" "tracktype"
## [213] "traffic_calming" "traffic_sign"
## [215] "trail_visibility" "trailblazed"
## [217] "trailblazed:visibility" "tunnel"
## [219] "turn" "type"
## [221] "usage" "vehicle"
## [223] "vending" "voltage"
## [225] "water" "wheelchair"
## [227] "wholesale" "width"
## [229] "winter_road" "wood"
Tenemos 230 keys, y como verán, son muy variadas. A su vez, dentro de cada key (amenity, shop, railway, etc.) encontraremos diferentes tags que podemos consultarlos de la siguiente forma:
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] "parcel_locker" "parking" "parking_entrance"
## [76] "parking_space" "pharmacy" "photo_booth"
## [79] "place_of_mourning" "place_of_worship" "planetarium"
## [82] "police" "post_box" "post_depot"
## [85] "post_office" "prison" "pub"
## [88] "public_bath" "public_bookcase" "public_building"
## [91] "ranger_station" "recycling" "refugee_site"
## [94] "restaurant" "sanitary_dump_station" "school"
## [97] "shelter" "shower" "social_centre"
## [100] "social_facility" "stripclub" "studio"
## [103] "swingerclub" "taxi" "telephone"
## [106] "theatre" "toilets" "townhall"
## [109] "toy_library" "university" "vehicle_inspection"
## [112] "vending_machine" "veterinary" "waste_basket"
## [115] "waste_disposal" "waste_transfer_station" "water_point"
## [118] "watering_place"
Podemos ver que, por ejemplo dentro de la key llamada amenity se encuentran diferentes tags o values como por ejemplo: bar, restaurant, heladería, hospital, biblioteca, etc.
Listo, hasta acá ya tenemos un poco más de información sobre el contenido posible de descargar. Ahora elijamos de que lugar del mundo queremos descargar la información!
Llegó el momento de decidir el sitio/lugar de donde queremos traernos información ya que no podremos descargar todos los datos que tiene OSM porque son millones! Para esto debemos crear un cuadro delimitador o bounding box con la función getbb() y el nombre de la Ciudad de interés:
bbox_montevideo <- getbb("Montevideo, Uruguay")
La función anterior nos devolverá 4 coordenadas (longitud máxima, longitud mínima, latitud máxima, latitud mínima) que representan los límites de la información a descargar. Esto nos servirá como insumo principal al momento de hacer una descarga de información geográfica de OSM. Es importante tener en cuenta que la Ciudad tiene que estar escrita con el mayor detalle posible (Ciudad, Provincia, País), así se evita que OSM descargue información de otra Ciudad que no sea la elegida. Para conocer el nombre exacto con el que OSM reconoce las Ciudades, pueden hacer una búsqueda rápida directamente en su sitio web.
Revisemos el resultado que obtuvimos:
bbox_montevideo
## min max
## x -56.43140 -56.02250
## y -34.93806 -34.70185
Aprovechemos lo que aprendimos en clases anteriores y descarguemos un mapa base a partir de get_stamenmap():
mapa_montevideo <- get_stamenmap(bbox=bbox_montevideo,
zoom=12)
Y veamos el resultado:
ggmap(mapa_montevideo)
Listo! Parece que todo salió bien! El mapa efectivamente es de Montevideo, Uruguay.
Para poder comprender mejor que extensión de territorio cubre Montevideo, sería muy útil que también tengamos mapeados los límites de la Ciudad, ¿No?
Por suerte podemos conseguirlo ajustando el parámetro format_out=“sf_polygon” en la función getbb() de la siguiente forma:
polygon_montevideo <- getbb("Montevideo, Uruguay",
format_out = "sf_polygon")
Veamos el resultado:
polygon_montevideo
## Simple feature collection with 2 features and 0 fields
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: -56.4314 ymin: -34.93806 xmax: -56.0225 ymax: -34.70185
## Geodetic CRS: WGS 84
## geometry
## 1 POLYGON ((-56.4314 -34.8281...
## 2 POLYGON ((-56.4314 -34.8281...
Al parecer nos descargamos 2 polígonos, pero solo queríamos 1 con los límites de Montevideo. Hagamos un breve análisis para ver si se trata de información duplicada:
polygon_montevideo <- polygon_montevideo %>%
mutate(ID=row.names(polygon_montevideo))
ggplot()+
geom_sf(data=polygon_montevideo)+
facet_wrap(~ID)
Efectivamente se trata de un polígono duplicado. Eliminemos uno de los 2 para evitar posibles problemas a la hora de descargar información.
polygon_montevideo <- polygon_montevideo[1,]
Ahora si, veamos como queda el mapa (recuerden que para agregar capas a un ggmap() debemos agregarle a cada capa extra el parámetro inherit.aes = FALSE):
ggmap(mapa_montevideo)+
geom_sf(data=polygon_montevideo, inherit.aes = FALSE)
Lo logramos! Hagamos algunos ajustes para mejorar la visualización: quitemos el relleno del polígono y pongamos título y fuente:
ggmap(mapa_montevideo)+
geom_sf(data=polygon_montevideo, fill=NA, color="red", size=1, inherit.aes = FALSE)+
labs(title="Montevideo, Uruguay",
caption="Fuente: Open Street Map")+
theme_void()
Para traernos información de OSM usaremos 3 funciones: opq() y add_osm_feature() para generar la consulta/requerimiento y osmdata_sf() para hacer la descarga. Tengamos en cuenta que con osmdata podemos descargar solamente datos vectoriales/geometrías representadas a partir de líneas, polígonos y puntos. Veamos un ejemplo de cada uno de ellos.
Como primer paso, asignemos el bounding box correspondiente a nuestro área de estudio dentro de opq() y en add_osm_feature() especifiquemos que key y/o values queremos.
En este caso probemos descargando los principales ejes viales (líneas) de toda la Ciudad de Montevideo, y que en OSM las encontramos con la key = “highway” y el value = c(“motorway”, “trunk”, “primary”, “secondary”):
vialidad_montevideo <- opq(bbox_montevideo) %>%
add_osm_feature(key = "highway", value = c("motorway", "trunk", "primary", "secondary"))
El segundo paso es utilizar la función osmdata_sf() para descargar toda la información seleccionada en el paso anterior:
vialidad_montevideo <- osmdata_sf(vialidad_montevideo)
Veamos que nos descargamos:
vialidad_montevideo
Nos pudimos descargar toda la información relacionada a los principales ejes viales que se encontró dentro de los límites establecidos: 9.523 puntos, 1.891 líneas y 3 polígonos.
Sin embargo solo necesitamos quedarnos con las líneas que representan los ejes de calles. Por lo tanto, el paso 3 es seleccionarlas con \(osm_lines* (cabe destacar que, si estaríamos buscando quedarnos con los puntos utilizaríamos *\)osm_points y con los polígonos $osm_polygons):
vialidad_montevideo <- vialidad_montevideo$osm_lines
Ahora si ya tenemos nuestros datos geográficos y podemos explorar el tamaño del dataset con dim():
dim(vialidad_montevideo)
## [1] 1891 71
Efectivamente tenemos las 1.891 líneas junto a 71 columnas/variables. Sumemos esto a nuestro mapa base:
ggmap(mapa_montevideo)+
geom_sf(data=polygon_montevideo, fill=NA, color="red", size=1, inherit.aes = FALSE)+
geom_sf(data = vialidad_montevideo, inherit.aes = FALSE)+
labs(title="Ejes Viales Principales",
subtitle="Montevideo, Uruguay",
caption="Fuente: Open Street Map")+
theme_void()
Podrán ver que las líneas se descargaron de acuerdo al límite del bounding box y no por los límites geográficos de Montevideo. Para solucionarlo alcanza con hacer una intersección entre ambos datos geográficos utilizando st_intersection():
vialidad_montevideo <- st_intersection(vialidad_montevideo, polygon_montevideo)
Veamos el resultado:
ggmap(mapa_montevideo)+
geom_sf(data=polygon_montevideo, fill=NA, color="red", size=1, inherit.aes = FALSE)+
geom_sf(data = vialidad_montevideo, inherit.aes = FALSE)+
labs(title="Ejes Viales Principales",
subtitle="Montevideo, Uruguay",
caption="Fuente: Open Street Map")+
theme_void()
También podemos colorear los ejes viales de acuerdo a algún atributo que tengan, como por ejemplo su tipología, su velocidad máxima, la cantidad de carriles, etc. Probemos con la tipología (highway):
ggmap(mapa_montevideo)+
geom_sf(data = vialidad_montevideo, aes(color=highway), size=1, inherit.aes = FALSE)+
labs(title="Ejes Viales Principales",
subtitle="Montevideo, Uruguay",
caption="Fuente: Open Street Map",
color="Tipo de Eje")+
scale_color_manual(values = c("firebrick3", "darkorange1", "blue4"))+
theme_void()
Los colores elegidos en el mapa anterior y muchos más pueden verse en este link. También se podrían utilizar los códigos HEX clásicos.
Y con la velocidad máxima (maxspeed):
ggmap(mapa_montevideo)+
geom_sf(data = vialidad_montevideo, aes(color=maxspeed), size=1, inherit.aes = FALSE)+
labs(title="Ejes Viales Principales",
subtitle="Montevideo, Uruguay",
caption="Fuente: Open Street Map",
color="Vel. Máx.")+
theme_void()