Qries eduard-martinez.github.io

Qries @emartigo

Qries eduard-martinez

Qries efmartinez@icesi.edu.co

[1.] Configuración Inicial

Para facilitar la reproducción de este ejercicio en sus propios equipos, puede descargar el siguiente script de R aquí.

En este bloque de código se realiza la configuración básica del entorno de trabajo. Para ello se utiliza el paquete pacman, que permite cargar múltiples paquetes de forma eficiente. Si un paquete no está instalado, pacman::p_load() lo instala automáticamente antes de cargarlo.

## llamar pacman 
require(pacman)

## llamar y/o instalar librerias
p_load(tidyverse,    ## tidy data
       rio,          ## leer/escribir conjuntos de datos
       sf,           ## datos espaciales
       mapview,      ## visualizaciones
       tidygeocoder, ## geocodificar
       ggspatial,    ## mapas base en ggplot2 (tiles OSM, Stamen, Esri) 
       osmdata)      ## packages osm data

Cada una de estas librerías cumple un rol importante en el flujo de trabajo para análisis espacial:

tidyverse: Facilita la manipulación, exploración y visualización de datos.

rio: Permite importar/exportar archivos en múltiples formatos (como .csv, .xlsx, .sav, entre otros).

sf: Es el estándar actual para el manejo de datos espaciales vectoriales en R.

mapview: Herramienta práctica para visualizar rápidamente objetos espaciales en mapas interactivos.

tidygeocoder: Proporciona una interfaz sencilla para convertir direcciones en coordenadas geográficas y viceversa.

ggspatial: Extiende las capacidades de ggplot2 para incluir mapas base (tiles) de proveedores como OpenStreetMap, Stamen y Esri, a través de la función annotation_map_tile(). Ideal para crear mapas estáticos de alta calidad y superponer objetos sf con contexto geográfico.

osmdata: Permite descargar datos vectoriales de OpenStreetMap, como calles, ríos, edificios, entre otros elementos geográficos.

Esta configuración inicial asegura que contamos con todas las herramientas necesarias para realizar análisis geoespaciales y geocodificación dentro de un entorno reproducible.

[2.] Geocodificar Direcciones

El paquete tidygeocoder permite realizar procesos de geocodificación (obtener coordenadas geográficas a partir de direcciones) y geocodificación inversa (obtener direcciones a partir de coordenadas) de forma sencilla y en formato tidy, ideal para trabajar con dplyr y tidyverse..

Aunque su función más conocida es geocode(), el paquete incluye otras funciones como geo() y reverse_geocode(), que permiten realizar tareas similares con menor complejidad o desde coordenadas.

A continuación se presentan los principales motores de geocodificación disponibles en tidygeocoder, indicando si requieren o no una clave API:

## Warning in attr(x, "align"): 'xfun::attr()' is deprecated.
## Use 'xfun::attr2()' instead.
## See help("Deprecated")
## Warning in attr(x, "format"): 'xfun::attr()' is deprecated.
## Use 'xfun::attr2()' instead.
## See help("Deprecated")
Metodo Motor Requiere.API.Key
osm OpenStreetMap Nominatim No
arcgis Esri ArcGIS No
google Google Maps
census US Census Bureau No (solo EE.UU.)
tomtom TomTom
bing Microsoft Bing Maps

La siguiente línea utiliza la función geo() para obtener las coordenadas (latitud y longitud) de una dirección específica. En este caso se utiliza el motor arcgis (de Esri), que no requiere clave API para este tipo de consultas. La función retorna un data.frame con las columnas address, lat y long.

## obtener las coordenadas de una dirección
geo("Universidad Icesi, Cali, Colombia" , method="arcgis") 
## # A tibble: 1 × 3
##   address                             lat  long
##   <chr>                             <dbl> <dbl>
## 1 Universidad Icesi, Cali, Colombia  3.34 -76.5

2.1. geo y sf

Aquí almacenamos el resultado de la geocodificación en un objeto llamado icesi, y verificamos su clase. Este objeto es inicialmente un data.frame, lo cual permite manipularlo fácilmente o convertirlo en otros formatos, como objetos espaciales.

## Almacenar la dirección en un objeto
icesi <- geo("Universidad Icesi, Cali, Colombia" , method="arcgis") 
class(icesi)
## [1] "tbl_df"     "tbl"        "data.frame"

Para trabajar con datos espaciales en R es común utilizar el paquete sf, que proporciona una estructura de datos geoespaciales moderna. Aquí usamos st_as_sf() para convertir el data.frame en un objeto espacial, indicando qué columnas contienen las coordenadas (long y lat) y especificando el sistema de referencia geográfica WGS 84 (crs = 4326).

## Convertir el objeto a SF
icesi <- st_as_sf(x=icesi , coords=c("long","lat") , crs=4326)
icesi
## Simple feature collection with 1 feature and 1 field
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -76.5296 ymin: 3.34165 xmax: -76.5296 ymax: 3.34165
## Geodetic CRS:  WGS 84
## # A tibble: 1 × 2
##   address                                     geometry
## * <chr>                                    <POINT [°]>
## 1 Universidad Icesi, Cali, Colombia (-76.5296 3.34165)

Finalmente, usamos la función mapview() para visualizar el punto geocodificado en un mapa interactivo. mapview es una herramienta sencilla y potente para inspeccionar visualmente objetos espaciales, añadiendo automáticamente una capa base de OpenStreetMap.

## la función mapview adiciona la capa de OpenStreetMap
mapview(icesi)

2.2. Geocodificar un vector de direcciones

En esta sección se realiza la geocodificación masiva de un conjunto de direcciones almacenadas en una base de datos. Este procedimiento es útil cuando se dispone de varias ubicaciones (por ejemplo, instituciones, oficinas, puntos de interés) y se desea obtener sus coordenadas geográficas para posterior análisis o visualización.

Se utiliza la función import() del paquete rio para leer una base de datos en formato .rds desde una URL. Esta base contiene un vector de direcciones de instituciones o puntos de interés en Cali, Colombia, en una columna llamada direccion.

## leer base de datos
cali <- import("https://eduard-martinez.github.io//workshop/gis_in_r/data/data_cali.rds")
## Warning: The `trust` argument of `import()` should be explicit for serialization formats
## as of rio 1.0.3.
## ℹ Missing `trust` will be set to FALSE by default for RDS in 2.0.0.
## ℹ The deprecated feature was likely used in the rio package.
##   Please report the issue at <https://github.com/gesistsa/rio/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
cali
##    id                                                     direccion
## 1   1                                    Cristo Rey, Cali, Colombia
## 2   2                             Zoológico de Cali, Cali, Colombia
## 3   3                             Museo La Tertulia, Cali, Colombia
## 4   4         Teatro Municipal Enrique Buenaventura, Cali, Colombia
## 5   5                              Plaza de Cayzedo, Cali, Colombia
## 6   6                      Cerro de las Tres Cruces, Cali, Colombia
## 7   7 Biblioteca Departamental Jorge Garcés Borrero, Cali, Colombia
## 8   8                  Alcaldía de Santiago de Cali, Cali, Colombia
## 9   9               Gobernación del Valle del Cauca, Cali, Colombia
## 10 10                       Centro Cultural de Cali, Cali, Colombia

Se utiliza la función geocode() del paquete tidygeocoder para obtener las coordenadas (latitud y longitud) asociadas a cada dirección en la columna direccion.cSe usa el motor arcgis, que no requiere clave API y ofrece buenos resultados para direcciones en Colombia.

La función añade automáticamente dos columnas nuevas: lat y long.

cali <- geocode(cali , address="direccion" , method="arcgis")
cali
## # A tibble: 10 × 4
##       id direccion                                                     lat  long
##    <int> <chr>                                                       <dbl> <dbl>
##  1     1 Cristo Rey, Cali, Colombia                                   3.44 -76.6
##  2     2 Zoológico de Cali, Cali, Colombia                            3.42 -76.5
##  3     3 Museo La Tertulia, Cali, Colombia                            3.45 -76.5
##  4     4 Teatro Municipal Enrique Buenaventura, Cali, Colombia        3.45 -76.5
##  5     5 Plaza de Cayzedo, Cali, Colombia                             3.45 -76.5
##  6     6 Cerro de las Tres Cruces, Cali, Colombia                     3.47 -76.5
##  7     7 Biblioteca Departamental Jorge Garcés Borrero, Cali, Colom…  3.44 -76.5
##  8     8 Alcaldía de Santiago de Cali, Cali, Colombia                 3.45 -76.5
##  9     9 Gobernación del Valle del Cauca, Cali, Colombia              3.44 -76.5
## 10    10 Centro Cultural de Cali, Cali, Colombia                      3.45 -76.5

El conjunto de datos cali se convierte en un objeto espacial de clase sf utilizando st_as_sf(), especificando que las columnas de coordenadas son long (longitud) y lat (latitud), y asignando el sistema de referencia geográfica WGS 84 (EPSG:4326), que es el estándar para coordenadas GPS.

cali <- st_as_sf(x=cali , coords=c("long","lat") , crs=4326)

Finalmente, se visualiza el resultado en un mapa interactivo con mapview(), lo cual permite explorar visualmente la distribución de los puntos sobre una capa base de OpenStreetMap.

mapview(cali)

[3.] OpenStreetMap

3.1. Acerca de OpenStreetMap

OpenStreetMap (OSM) es un proyecto colaborativo de mapeo global y de acceso abierto, similar a una “Wikipedia de los mapas”. Fue creado con el objetivo de generar una base de datos geográficos libre y accesible para todos, y se construye con contribuciones de voluntarios que utilizan GPS, imágenes satelitales y otras fuentes abiertas.

OSM es gratuito y está licenciado bajo la Open Database License (ODbL), lo cual permite su uso, modificación y redistribución con algunas condiciones de atribución.

3.2. Librería osmdata en R

En R, el paquete osmdata permite acceder directamente a los datos de OSM mediante consultas a la API Overpass, la cual filtra y extrae información específica desde la base de datos global.

Con osmdata se pueden consultar objetos espaciales como calles, hospitales, estaciones de buses, edificios, parques, ciclovías y mucho más. La librería facilita descargar, transformar y visualizar estos datos en estructuras compatibles con sf.

3.3. Features y Tags disponibles en OSM

En OpenStreetMap, los elementos geográficos se describen mediante features (categorías generales) y tags (atributos específicos). Para explorar qué categorías (features) existen en OSM, se puede utilizar la función available_features(). Esto devuelve un vector con nombres de elementos como highway, building, amenity, landuse, entre otros.

## Ver features disponibles
available_features() %>% head(20)
##  [1] "4wd_only"                "abandoned"              
##  [3] "abutters"                "access"                 
##  [5] "addr"                    "addr:*"                 
##  [7] "addr:city"               "addr:conscriptionnumber"
##  [9] "addr:country"            "addr:county"            
## [11] "addr:district"           "addr:flats"             
## [13] "addr:full"               "addr:hamlet"            
## [15] "addr:housename"          "addr:housenumber"       
## [17] "addr:inclusion"          "addr:interpolation"     
## [19] "addr:place"              "addr:postbox"

Cada feature tiene un conjunto de posibles etiquetas (tags). Por ejemplo, si queremos explorar los tipos de amenity (equipamientos):

## Ver tags de una feature
available_tags("amenity") %>% head(20)
## # A tibble: 20 × 2
##    Key     Value                 
##    <chr>   <chr>                 
##  1 amenity animal_boarding       
##  2 amenity animal_breeding       
##  3 amenity animal_shelter        
##  4 amenity animal_training       
##  5 amenity arts_centre           
##  6 amenity atm                   
##  7 amenity baby_hatch            
##  8 amenity baking_oven           
##  9 amenity bank                  
## 10 amenity bar                   
## 11 amenity bbq                   
## 12 amenity bench                 
## 13 amenity bicycle_parking       
## 14 amenity bicycle_rental        
## 15 amenity bicycle_repair_station
## 16 amenity bicycle_wash          
## 17 amenity biergarten            
## 18 amenity boat_rental           
## 19 amenity boat_sharing          
## 20 amenity brothel

Esto devuelve tags como school, hospital, bus_station, cafe, entre otros.

También puede consultar la documentación oficial de features y tags de OSM en este enlace: Map Features - OSM Wiki

3.4. Descargar Features desde OpenStreetMap

El proceso para descargar datos desde OSM con osmdata incluye 3 pasos fundamentales:

3.4.1. Definir un área geográfica con getbb()

Antes de consultar OSM, es necesario definir una “bounding box” o caja de coordenadas que delimite la zona de interés. Se puede usar el nombre de una ciudad o país:

opq(bbox = getbb("Cali Colombia"))
## $bbox
## [1] "3.2734085,-76.7069442,3.548577,-76.4588983"
## 
## $prefix
## [1] "[out:xml][timeout:25];\n(\n"
## 
## $suffix
## [1] ");\n(._;>;);\nout body;"
## 
## $features
## NULL
## 
## $osm_types
## [1] "node"     "way"      "relation"
## 
## attr(,"class")
## [1] "list"           "overpass_query"
## attr(,"nodes_only")
## [1] FALSE

getbb() obtiene automáticamente las coordenadas que encierran el área especificada.

3.4.2. Construir la consulta con add_osm_feature()

Se define el tipo de información que se desea descargar usando una combinación de key y value. Por ejemplo, para obtener restaurantes:

osm <- opq(bbox = getbb("Cali Colombia")) %>%
       add_osm_feature(key = "amenity", value = "restaurant")

El objeto resultante es una consulta a la API de OSM que aún no se ha ejecutado. Su clase es overpass_query.

3.4.3. Ejecutar la consulta y convertir a sf

Con osmdata_sf() se ejecuta la consulta y se obtiene una lista con objetos espaciales en formato sf:

osm_sf <- osmdata_sf(osm)

Este objeto contiene elementos como:

osm_points: objetos puntuales (coordenadas)

osm_lines: líneas (como calles)

osm_polygons: polígonos (como edificios o parques)

3.4.4. Extraer y visualizar los puntos

Por ejemplo, para obtener solo los puntos de tipo restaurante:

rest_cali <- osm_sf$osm_points %>% select(osm_id, name , amenity)
class(rest_cali)
## [1] "sf"         "data.frame"

Y para visualizar el resultado de forma interactiva:

mapview(rest_cali, color = "red")

Esto genera un mapa con los puntos representando los restaurantes en Calí, utilizando una base de OpenStreetMap. mapview es muy útil para inspecciones visuales rápidas durante la exploración y validación de datos espaciales.

Este flujo permite enriquecer cualquier análisis espacial con datos abiertos actualizados, sin necesidad de descargar archivos manualmente. Además, la integración con sf y mapview permite realizar análisis y visualización directamente en R.

3.5. Más allá de los puntos: descargar otros tipos de datos desde OSM

En este último ejemplo, se utiliza getbb() para obtener una geometría de tipo polígono correspondiente al barrio Granada en Cali. En lugar de devolver solo una caja de coordenadas (bounding box), aquí se indica que se desea una geometría de tipo sf_polygon. Esto permite trabajar con unidades administrativas o barrios específicos de manera más precisa.

granada <- getbb(place_name = "Granada, Cali", 
                 featuretype = "boundary:administrative", 
                 format_out = "sf_polygon")

mapview(granada)

El resultado es un objeto de clase sf que representa el límite administrativo del área consultada. Esto puede ser muy útil para delimitar zonas de interés antes de realizar consultas más específicas (por ejemplo, todos los parques, restaurantes u oficinas públicas dentro de Granada).

[4.] Operaciones Geométricas

4.1. Librería sf

La librería sf (Simple Features) es el estándar moderno para manejar datos espaciales vectoriales en R. Su integración con dplyr y su compatibilidad con otras librerías como ggplot2, mapview o leaflet la convierten en una herramienta central para cualquier flujo de trabajo geoespacial.

## Documentación extendida de sf
vignette("sf3")  # Reading, writing and converting simple features
vignette("sf4")  # Geometry operations

4.2. Filtrar Geometrías

Una operación muy común en el análisis espacial es filtrar los objetos que se encuentran dentro de una zona específica. En este caso, se recorta el conjunto de restaurantes (rest_cali) para conservar únicamente aquellos que están dentro del barrio Granada, utilizando la función st_crop():

rest_grana <- st_crop(x=rest_cali , y=granada  , mask=T)
## Warning: attribute variables are assumed to be spatially constant throughout
## all geometries

x: objeto espacial a recortar (Restaurantes).

y: geometría de recorte (barrio Granada).

mask = TRUE: garantiza que el resultado se recorta exactamente al polígono.

Para verificar cuántos restaurantes hay antes y después del recorte:

nrow(rest_cali)
## [1] 655
nrow(rest_grana)
## [1] 48

Finalmente, se visualiza el resultado de forma interactiva:

mapview(granada , color="red") + mapview(rest_grana)

4.3. Calcular Distancias Geodésicas

Otra operación fundamental es el cálculo de distancias entre objetos espaciales. En este caso, se calcula la distancia desde el punto icesi (previamente geocodificado) a cada uno de los puntos en el objeto cali (direcciones institucionales en Cali):

cali$dist <- st_distance(x=cali , y=icesi)
cali %>% head()
## Simple feature collection with 6 features and 3 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -76.56479 ymin: 3.4151 xmax: -76.53246 ymax: 3.46732
## Geodetic CRS:  WGS 84
## # A tibble: 6 × 4
##      id direccion                                         geometry dist[,1]
##   <int> <chr>                                          <POINT [°]>      [m]
## 1     1 Cristo Rey, Cali, Colombia            (-76.56479 3.435925)   11187.
## 2     2 Zoológico de Cali, Cali, Colombia       (-76.53472 3.4151)    8187.
## 3     3 Museo La Tertulia, Cali, Colombia      (-76.54514 3.45049)   12225.
## 4     4 Teatro Municipal Enrique Buenaventur… (-76.53585 3.449456)   12008.
## 5     5 Plaza de Cayzedo, Cali, Colombia       (-76.53246 3.45176)   12248.
## 6     6 Cerro de las Tres Cruces, Cali, Colo…  (-76.54619 3.46732)   14095.
cali$dist <- as.numeric(cali$dist)/1000

La función st_distance() devuelve una matriz de distancias geodésicas entre los elementos de dos objetos espaciales. En este caso, se calcula la distancia entre cada punto de cali y el punto único de icesi.

Dado que icesi contiene un solo punto, el resultado es una columna con una distancia por cada fila de cali. Es decir, se mide la distancia entre cada dirección en Cali y la Universidad Icesi.

Las distancias se expresan por defecto en metros, ya que el sistema de referencia espacial (crs) utilizado es WGS 84 (EPSG:4326). Este tipo de cálculo permite realizar análisis como encontrar la ubicación más cercana, establecer zonas de influencia o clasificar puntos por cercanía a un lugar de referencia.

[5.] Visualizar Datos Espaciales

El paquete ggplot2, parte del ecosistema tidyverse, también permite trabajar con objetos espaciales gracias a la función geom_sf(). A diferencia de mapview, que es interactivo, ggplot2 permite crear gráficos estáticos personalizables, ideales para informes, artículos o publicaciones.

Este gráfico muestra todos los puntos del objeto espacial cali sin aplicar ninguna estética adicional. Es útil para una visualización rápida de la distribución espacial de los datos.

## basic plot
ggplot() + geom_sf(data=cali , size=3)

En este gráfico se utiliza la variable dist (distancia a Icesi) como estética para asignar color a los puntos. De esta forma, el color representa la proximidad de cada ubicación respecto a la Universidad Icesi. Esta técnica permite comunicar información cuantitativa a través de una representación espacial.

## plot variable
ggplot() + geom_sf(data=cali , aes(color=dist) , size=3)

Aquí se mejora la visualización anterior utilizando la paleta Viridis, que es perceptualmente uniforme y adecuada para personas con daltonismo. Se define también el tamaño de los puntos (size = 3) para darles mayor visibilidad. El uso de scale_color_viridis_b() permite crear una escala de color continua bien definida y estéticamente agradable para representar valores numéricos.

## plot variable + scale
map <- ggplot() + 
       geom_sf(data=cali , aes(color=dist) , size=3) +
       scale_color_viridis_b(option = "D") +
       theme_minimal()
map 

Ahora, se incorpora un mapa base utilizando annotation_map_tile() del paquete ggspatial, que permite agregar mosaicos (tiles) provenientes de OpenStreetMap (OSM), Carto, Stamen, entre otros. El parámetro zoom controla el nivel de detalle (mayores valores → más zoom), y type = “osm” indica que se desea usar OpenStreetMap como fondo.

## plot variable + scale
map <- ggplot() + 
       annotation_map_tile(type="osm" , zoom=14) +
       geom_sf(data=cali , aes(color=dist) , size=3) +
       scale_color_viridis_b(option = "D") +
       theme_minimal()
map 

Finalmente, se añaden dos elementos cartográficos importantes:

•   Una flecha de norte, que orienta al lector respecto a la dirección geográfica.
•   Una barra de escala, que indica la relación entre la distancia en el mapa y la distancia real.

Ambos elementos se agregan con funciones del paquete ggspatial y pueden personalizarse en estilo y ubicación.

map +
annotation_north_arrow(location="tr" , which_north="true" , style=north_arrow_fancy_orienteering) +
annotation_scale(location = "bl",width_hint = 0.4) 

Referencias

  • Lovelace, R., Nowosad, J., & Muenchow, J. (2019). Geocomputation with R. [Ver aquí]

    • Cap. 4: Spatial Data Operations
    • Cap. 5: Geometry Operations
    • Cap. 6: Reprojecting geographic data
    • Cap. 11: Statistical learning
  • Bivand, R. S., Pebesma, E. J., Gómez-Rubio, V., & Pebesma, E. J. (2013). Applied spatial data analysis with R. [Ver aquí]

    • Cap. 4: Spatial Data Import and Export
    • Cap. 7: Spatial Point Pattern Analysis
    • Cap. 8: Interpolation and Geostatistics
  • Pebesma, E. (2018). Simple Features for R: Standardized Support for Spatial Vector Data. Ver artículo

  • Curso de Earth Data Science - University of Colorado. Ver curso