En este cuaderno se ilustra como obtener, procesar y visualizar modelos digitales de elevación (DEM) en R.
Instalar los paquetes necesarios para elaborar el trabajo, estos son: “rgdal”,“raster”, “rgeos”, terra”,“elevatr”,“rasterVis”, “rgl”, “mapview”
Limpiar memoria
rm(list=ls())
Cargar librerias
library(rasterVis)
library(raster)
#library(terra)
library(rgeos)
library(rgdal)
library(elevatr)
library(sf)
library(tidyverse)
library(mapview)
library(ggplot2)
library(leaflet)
library(tmap)
library(RColorBrewer)
Se usa el paquete elevatr para acceder a los datos de elevación desde las APl web
Primero se cargara un shapefile que represente los municipios de nuestro(s) departamento(S). En este caso se usara un shapefile que contiene los municipios de Caldas, Quindio y Risaralda.
(mun.eje = st_read('C:/Users/LENOVO/Desktop/Geomatica/R/Datos/muni_eje.shp'))
## Reading layer `muni_eje' from data source
## `C:\Users\LENOVO\Desktop\Geomatica\R\Datos\muni_eje.shp' using driver `ESRI Shapefile'
## Simple feature collection with 51 features and 14 fields
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: -76.3595 ymin: 4.135801 xmax: -74.6489 ymax: 5.7626
## Geodetic CRS: WGS 84
## Simple feature collection with 51 features and 14 fields
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: -76.3595 ymin: 4.135801 xmax: -74.6489 ymax: 5.7626
## Geodetic CRS: WGS 84
## First 10 features:
## fid ID_0 ISO NAME_0 ID_1 NAME_1 ID_2 NAME_2 TYPE_2 ENGTYPE_2
## 1 1 53 COL Colombia 8 Caldas 348 Aguadas Municipio Municipality
## 2 2 53 COL Colombia 8 Caldas 349 Anserma Municipio Municipality
## 3 3 53 COL Colombia 8 Caldas 350 Aranzazú Municipio Municipality
## 4 4 53 COL Colombia 8 Caldas 351 Belalcázar Municipio Municipality
## 5 5 53 COL Colombia 8 Caldas 352 Chinchiná Municipio Municipality
## 6 6 53 COL Colombia 8 Caldas 353 Filadelfia Municipio Municipality
## 7 7 53 COL Colombia 8 Caldas 354 La Dorada Municipio Municipality
## 8 8 53 COL Colombia 8 Caldas 355 La Merced Municipio Municipality
## 9 9 53 COL Colombia 8 Caldas 356 Manizales Municipio Municipality
## 10 10 53 COL Colombia 8 Caldas 357 Manzanares Municipio Municipality
## NL_NAME_2 VARNAME_2 Area codigo geometry
## 1 <NA> <NA> 501.64063 17013 POLYGON ((-75.3399 5.458, -...
## 2 <NA> <NA> 196.73857 17616 POLYGON ((-75.6908 5.152099...
## 3 <NA> Aranzazé 140.63766 17050 POLYGON ((-75.3997 5.2202, ...
## 4 <NA> <NA> 114.27085 17088 POLYGON ((-75.7841 5.032401...
## 5 <NA> <NA> 125.39270 17174 POLYGON ((-75.6204 4.979101...
## 6 <NA> <NA> 202.22182 17272 POLYGON ((-75.5888 5.207699...
## 7 <NA> <NA> 583.68634 17380 POLYGON ((-74.8504 5.290101...
## 8 <NA> <NA> 90.16428 17388 POLYGON ((-75.6437 5.362199...
## 9 <NA> <NA> 443.87241 17001 POLYGON ((-75.636 5.0011, -...
## 10 <NA> <NA> 171.87523 17433 POLYGON ((-75.1662 5.1453, ...
municipioseje <- data.frame(mun.eje)
Despues se comprueba la geometria, el cuadro delimitador, el CRS y los atributos del objeto municipioseje
head(municipioseje)
## fid ID_0 ISO NAME_0 ID_1 NAME_1 ID_2 NAME_2 TYPE_2 ENGTYPE_2
## 1 1 53 COL Colombia 8 Caldas 348 Aguadas Municipio Municipality
## 2 2 53 COL Colombia 8 Caldas 349 Anserma Municipio Municipality
## 3 3 53 COL Colombia 8 Caldas 350 Aranzazú Municipio Municipality
## 4 4 53 COL Colombia 8 Caldas 351 Belalcázar Municipio Municipality
## 5 5 53 COL Colombia 8 Caldas 352 Chinchiná Municipio Municipality
## 6 6 53 COL Colombia 8 Caldas 353 Filadelfia Municipio Municipality
## NL_NAME_2 VARNAME_2 Area codigo geometry
## 1 <NA> <NA> 501.6406 17013 POLYGON ((-75.3399 5.458, -...
## 2 <NA> <NA> 196.7386 17616 POLYGON ((-75.6908 5.152099...
## 3 <NA> Aranzazé 140.6377 17050 POLYGON ((-75.3997 5.2202, ...
## 4 <NA> <NA> 114.2709 17088 POLYGON ((-75.7841 5.032401...
## 5 <NA> <NA> 125.3927 17174 POLYGON ((-75.6204 4.979101...
## 6 <NA> <NA> 202.2218 17272 POLYGON ((-75.5888 5.207699...
Ahora, crearemos un nuevo objeto con los centroides de los municipios
# La tarea consiste en encontar un punto central para cada región
#Convertimos las caracteristicas simples en poligonos espaciales
sp.mun.eje = as_Spatial(mun.eje)
centers <- data.frame(gCentroid(sp.mun.eje, byid = TRUE))
centers$region <- row.names(sp.mun.eje)
centers$munic <- sp.mun.eje$NAME_2
head(centers)
## x y region munic
## 1 -75.48755 5.590398 1 Aguadas
## 2 -75.79169 5.204271 2 Anserma
## 3 -75.50984 5.255189 3 Aranzazú
## 4 -75.85170 4.981161 4 Belalcázar
## 5 -75.70418 4.975228 5 Chinchiná
## 6 -75.62369 5.282661 6 Filadelfia
Descargaremos los datos de elevación para nuestro(s) departamento(s)
# z indica el nivel de zoom de los datos
# a mayor zoom mayor resolución espacial
elevation <- get_elev_raster(mun.eje, z = 10)
## Mosaicing & Projecting
## Note: Elevation units are in meters.
elevation
## class : RasterLayer
## dimensions : 3066, 3078, 9437148 (nrow, ncol, ncell)
## resolution : 0.0006853648, 0.0006853648 (x, y)
## extent : -76.64062, -74.53107, 3.864425, 5.965754 (xmin, xmax, ymin, ymax)
## crs : +proj=longlat +datum=WGS84 +no_defs
## source : file175c72b8762c.tif
## names : file175c72b8762c
Se tiene que el tamaño de celda es: 0.0006853648, 0.0006853648 (x, y)
La elevacion es una capa raster temporal, sin embargo, es posible escribir el DEM en su directorio local usando la función writeRaster.
if (require(rgdal)) {
rf <- writeRaster(elevation, filename=file.path("./eje_dem_z10.tif"), format="GTiff", overwrite=TRUE)
}
Para visualizar, una resolución mas baja agiliza la tarea.
elevation2 <- aggregate(elevation, fact=4, fun=mean)
crs(elevation2) <- "+proj=longlat +datum=WGS84"
Una buena paleta es clave para una visulización adecuada. Probaremos con la siguiente:
pal <- colorNumeric(c("forestgreen","yellow","tan","brown"), values(elevation2),
na.color = "transparent")
Ahora, utilizaremos la biblioteca leaflet para ver los datos de elevación.
leaflet(mun.eje) %>% addTiles() %>%
addPolygons(color = "white", weight = 1.0, smoothFactor = 0.5,
opacity = 0.25, fillOpacity = 0.15,
popup = paste("Region: ", mun.eje$NAME_2, "<br>",
"Km2: ", mun.eje$Area, "<br>")) %>%
addLabelOnlyMarkers(data = centers,
lng = ~x, lat = ~y, label = ~region,
labelOptions = labelOptions(noHide = TRUE, direction = 'top', textOnly = TRUE)) %>%
addRasterImage(elevation2, colors = pal, opacity = 0.9) %>%
addLegend(pal = pal, values = values(elevation2),
title = "Datos de elevación para el eje cafetero (mts)")
Haz clic en el ID de cada región para obtener el nombre y la extensión del municipio.
Cuando se trabaja con un DEM, se recomienda utilizar coordenadas cartograficas en lugar de coordenadas geograficas.
Para reproyectar los datos de elevación en coordenadas cartograficas realizaremos dos pasos.
Primero. Definir el CRS del objeto.
spatialref <- CRS(SRS_string="EPSG:32618")
Despues, reproyectar el DEM usando la función projectRaster
# Primero creamos un objeto raster
pr3 <- projectExtent(elevation, crs=spatialref)
# Ajusta el tamaño de celda al tuyo
res(pr3) <- 80
#proyectalo
rep_elev <- projectRaster(elevation, pr3)
¿Que se obtiene?
rep_elev
## class : RasterLayer
## dimensions : 2907, 2928, 8511696 (nrow, ncol, ncell)
## resolution : 80, 80 (x, y)
## extent : 317827, 552067, 427129.2, 659689.2 (xmin, xmax, ymin, ymax)
## crs : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs
## source : memory
## names : file175c72b8762c
## values : -267.5508, 5280.105 (min, max)
Ahora, reproyectaremos el SpatialPolygons DataFrame, el cual representa los municipios de nuestro(s) departamento(s)
(rep_mun.eje = spTransform(sp.mun.eje,spatialref))
## class : SpatialPolygonsDataFrame
## features : 51
## extent : 349337, 538878.8, 457177.6, 636970.4 (xmin, xmax, ymin, ymax)
## crs : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs
## variables : 14
## names : fid, ID_0, ISO, NAME_0, ID_1, NAME_1, ID_2, NAME_2, TYPE_2, ENGTYPE_2, NL_NAME_2, VARNAME_2, Area, codigo
## min values : 1, 53, COL, Colombia, 8, Caldas, 348, Aguadas, Municipio, Municipality, NA, Aranzazé, 30.5922403667703, 17001
## max values : 51, 53, COL, Colombia, 25, Risaralda, 851, Viterbo, Municipio, Municipality, NA, Mantequilla, 1033.6076464384, 66687
Para evitar problemas, guardaremos nuestro DEM.
writeRaster(rep_elev, filename="./rep_eje_dem.tif", datatype='INT4S', overwrite=TRUE)
Debemos limpiar la elevación inferior a 0.0
rep_elev[rep_elev < 0.0] <- 0.0
Vamos a crear histograma con los valores de elevación
hist(rep_elev, main = "Histograma elevacion", col= "green")
Resumen de las estadisticas DEM
promedio <- cellStats(rep_elev, 'mean')
minimo <- cellStats(rep_elev, 'min')
maximo <- cellStats(rep_elev, 'max')
desviacion <- cellStats(rep_elev, 'sd')
Ahora crearemos un vector unidimensional con las estadisticas
metricas <- c('mean', 'min', 'max', 'std')
valores <- c(promedio, minimo, maximo, desviacion)
(df_estadisticas <- data.frame(metricas, valores))
## metricas valores
## 1 mean 1358.0057
## 2 min 0.0000
## 3 max 5280.1046
## 4 std 962.5001
Calcularemos la pendiente, el aspecto y el relieve
slope = terrain(rep_elev,opt='slope', unit='degrees')
aspect = terrain(rep_elev,opt='aspect',unit='degrees')
hill = hillShade(slope,aspect,40,315)
Resultados:
Pendiente
slope
## class : RasterLayer
## dimensions : 2907, 2928, 8511696 (nrow, ncol, ncell)
## resolution : 80, 80 (x, y)
## extent : 317827, 552067, 427129.2, 659689.2 (xmin, xmax, ymin, ymax)
## crs : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs
## source : memory
## names : slope
## values : 0, 85.36249 (min, max)
Aspecto
aspect
## class : RasterLayer
## dimensions : 2907, 2928, 8511696 (nrow, ncol, ncell)
## resolution : 80, 80 (x, y)
## extent : 317827, 552067, 427129.2, 659689.2 (xmin, xmax, ymin, ymax)
## crs : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs
## source : memory
## names : aspect
## values : 0, 360 (min, max)
Para hacer un plot de la pendiente debemos reducir el tamaño de la capa raster
# Usalo cuando el zoom sea muy alto
slope2 <- aggregate(slope, fact=4, fun=mean)
Es conveniente proyectar los datos de elevación
slope3 <- projectRasterForLeaflet(slope2, "ngb")
Tambien crear una paleta de colores
pal2 <- colorNumeric(c("#537188", "#CBB279", "#E1D4BB", "#EEEEEE"), values(slope3),na.color = "transparent")
Ahora, realizamos el plot
leaflet(mun.eje) %>% addTiles() %>%
addPolygons(color = "white", weight = 1.0, smoothFactor = 0.5,
opacity = 0.25, fillOpacity = 0.15,
popup = paste("Region: ", mun.eje$NAME_2, "<br>",
"Km2: ", mun.eje$Area, "<br>")) %>%
addLabelOnlyMarkers(data = centers,
lng = ~x, lat = ~y, label = ~region,
labelOptions = labelOptions(noHide = TRUE, direction = 'top', textOnly = TRUE)) %>%
addRasterImage(slope3, colors = pal2, opacity = 1.0) %>%
addLegend(pal = pal2, values = values(slope3),
title = "Pendiente Eje cafetero (%)")
¿Que es el objeto slope2?
slope2
## class : RasterLayer
## dimensions : 727, 732, 532164 (nrow, ncol, ncell)
## resolution : 320, 320 (x, y)
## extent : 317827, 552067, 427049.2, 659689.2 (xmin, xmax, ymin, ymax)
## crs : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs
## source : memory
## names : slope
## values : 0.09009511, 83.27359 (min, max)
Ahora, Convertiremos un Rasterlayer (objeto raster) en un SpatRaster (objeto terra)
(nslope2 <- as(slope2, "SpatRaster"))
## class : SpatRaster
## dimensions : 727, 732, 1 (nrow, ncol, nlyr)
## resolution : 320, 320 (x, y)
## extent : 317827, 552067, 427049.2, 659689.2 (xmin, xmax, ymin, ymax)
## coord. ref. : WGS 84 / UTM zone 18N (EPSG:32618)
## source(s) : memory
## name : slope
## min value : 0.09009511
## max value : 83.27359377
La clasificación de pendientes es importante para entender la variabilidad del relieve. Es necesario introducir una tabla con los intervalos de pendiente, los nombres de las clases y la descripción, tal como establece el IGAC.
Se realizará una clasificación de pendientes basada en intervalos comunes.
Primero, creamos una matriz de reclasificación.
m <- c(0, 3, 1, 3, 7, 2, 7,12,3, 12,
25, 4, 25, 50, 5, 50, 75, 6, 75, 100, 7)
(rclmat <- matrix(m, ncol=3, byrow = TRUE))
## [,1] [,2] [,3]
## [1,] 0 3 1
## [2,] 3 7 2
## [3,] 7 12 3
## [4,] 12 25 4
## [5,] 25 50 5
## [6,] 50 75 6
## [7,] 75 100 7
La matriz anterior clasifica en diferentes categorias la pendiente que se presenta en un terreno a partir de su valor expresado en porcentaje. Esto muestra que hay 7 clasificaciones categoricas para la pendiente, tal como se puede observar en la ultima columna. La interpretacion para las categorias de pendiente 1, 2, 3, 4, 5, 6, 7, obtenidas en la ultima columna, son respectivamente: A nivel, Ligeramente inclinada, Moderadamente inclinada, Fuertemente inclinada, Ligeramente empinada, Moderadamente empinada, Fuertemente empinada.
Reclasificación:
slope_rec <- terra::classify(nslope2, rclmat, right=TRUE)
slope_rec
## class : SpatRaster
## dimensions : 727, 732, 1 (nrow, ncol, nlyr)
## resolution : 320, 320 (x, y)
## extent : 317827, 552067, 427049.2, 659689.2 (xmin, xmax, ymin, ymax)
## coord. ref. : WGS 84 / UTM zone 18N (EPSG:32618)
## source(s) : memory
## name : slope
## min value : 1
## max value : 7
Usaremos tmap para crear y guardar un mapa estatico de clasificación de pendientes.
slope.map <- tm_shape(slope_rec) +
tm_raster(alpha = 0.6, style= "cat",
title="Pendiente") +
# Borders only
tm_shape(mun.eje) + tm_borders(col = "darkgray", lwd = 0.5, alpha=0.8) +
tm_text(text = "NAME_2", size = 0.3, alpha=0.7) +
tm_scale_bar(text.size = 0.5) +
tm_compass(position = c("right", "top"), size = 2) +
tm_graticules(alpha = 0.2) +
tm_layout(outer.margins = 0.01, legend.position = c("left", "top"), title= 'clases de pendiente', title.position = c('right', 'top')) +
tm_credits("Data source: Mapzen & DANE", size=0.3)
Visualizar
slope.map
Guardaremos el mapa
tmap_save(slope.map, "./eje_slope.png", width = 8.5, height =11, dpi=600)
## Map saved to C:\Users\LENOVO\Desktop\Geomatica\R\eje_slope.png
## Resolution: 5100 by 6600 pixels
## Size: 8.5 by 11 inches (600 dpi)
Ahora haremos un mapa de pendiente interactivo.
Convertir el objeto sf en un objeto SpatVector
(nmun.eje <- as(rep_mun.eje, "SpatVector"))
## class : SpatVector
## geometry : polygons
## dimensions : 51, 14 (geometries, attributes)
## extent : 349337, 538878.8, 457177.6, 636970.4 (xmin, xmax, ymin, ymax)
## coord. ref. : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs
## names : fid ID_0 ISO NAME_0 ID_1 NAME_1 ID_2 NAME_2 TYPE_2
## type : <num> <num> <chr> <chr> <num> <chr> <num> <chr> <chr>
## values : 1 53 COL Colombia 8 Caldas 348 Aguadas Municipio
## 2 53 COL Colombia 8 Caldas 349 Anserma Municipio
## 3 53 COL Colombia 8 Caldas 350 Aranzazú Municipio
## ENGTYPE_2 (and 4 more)
## <chr>
## Municipality
## Municipality
## Municipality
Convertir el objeto raster en un objeto terra
(nslope <- as(slope, "SpatRaster"))
## class : SpatRaster
## dimensions : 2907, 2928, 1 (nrow, ncol, nlyr)
## resolution : 80, 80 (x, y)
## extent : 317827, 552067, 427129.2, 659689.2 (xmin, xmax, ymin, ymax)
## coord. ref. : WGS 84 / UTM zone 18N (EPSG:32618)
## source(s) : memory
## name : slope
## min value : 0.00000
## max value : 85.36249
Calculemos las categorias de pendientes agregadas por municipio:
mun.eje.slope <- zonal(nslope, nmun.eje, fun=mean, as.raster=TRUE)
Objeto terra:
mun.eje.slope
## class : SpatRaster
## dimensions : 2907, 2928, 1 (nrow, ncol, nlyr)
## resolution : 80, 80 (x, y)
## extent : 317827, 552067, 427129.2, 659689.2 (xmin, xmax, ymin, ymax)
## coord. ref. : WGS 84 / UTM zone 18N (EPSG:32618)
## source(s) : memory
## name : slope
## min value : 2.281582
## max value : 28.282159
Visualización del mapa
tmap_mode("view")
## tmap mode set to interactive viewing
tm_shape(mun.eje) + tm_borders(col = "darkgray", lwd = 0.5, alpha=0.8) +
tm_text(text = "NAME_2", size = 0.5, alpha=0.7) +
tm_shape(mun.eje.slope) +
tm_raster(style="cont", n=7, alpha=0.6, title="Mean slope")+
tm_layout(legend.outside = TRUE)
## stars object downsampled to 1004 by 997 cells. See tm_shape manual (argument raster.downsample)
Este trabajo se realizó tomando como guía el cuaderno: Lizarazo, I. 2023, Elevation data processing and analysis in R.
Cite este trabajo así: Cely, N., 2023. Procesamiento y análisis de datos de elevación en R. Disponible en https://rpubs.com/ncely/1048046
sessionInfo()
## R version 4.2.2 (2022-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 22621)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8 LC_CTYPE=Spanish_Colombia.utf8
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C
## [5] LC_TIME=Spanish_Colombia.utf8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] RColorBrewer_1.1-3 tmap_3.3-3 leaflet_2.1.2 mapview_2.11.0
## [5] lubridate_1.9.2 forcats_1.0.0 stringr_1.5.0 dplyr_1.1.2
## [9] purrr_1.0.1 readr_2.1.4 tidyr_1.3.0 tibble_3.2.1
## [13] ggplot2_3.4.2 tidyverse_2.0.0 sf_1.0-13 elevatr_0.4.2
## [17] rgdal_1.6-6 rgeos_0.6-3 raster_3.6-20 sp_1.6-0
## [21] rasterVis_0.51.5 lattice_0.20-45
##
## loaded via a namespace (and not attached):
## [1] satellite_1.0.4 httr_1.4.6 progress_1.2.2
## [4] webshot_0.5.4 tools_4.2.2 bslib_0.4.2
## [7] utf8_1.2.3 R6_2.5.1 KernSmooth_2.23-20
## [10] DBI_1.1.3 colorspace_2.1-0 withr_2.5.0
## [13] prettyunits_1.1.1 tidyselect_1.2.0 curl_5.0.0
## [16] compiler_4.2.2 progressr_0.13.0 leafem_0.2.0
## [19] cli_3.6.1 sass_0.4.6 scales_1.2.1
## [22] classInt_0.4-9 hexbin_1.28.3 proxy_0.4-27
## [25] digest_0.6.31 rmarkdown_2.21 base64enc_0.1-3
## [28] dichromat_2.0-0.1 jpeg_0.1-10 pkgconfig_2.0.3
## [31] htmltools_0.5.5 highr_0.10 fastmap_1.1.1
## [34] htmlwidgets_1.6.2 rlang_1.1.1 rstudioapi_0.14
## [37] farver_2.1.1 jquerylib_0.1.4 generics_0.1.3
## [40] zoo_1.8-12 jsonlite_1.8.4 crosstalk_1.2.0
## [43] magrittr_2.0.3 s2_1.1.4 interp_1.1-4
## [46] Rcpp_1.0.10 munsell_0.5.0 fansi_1.0.4
## [49] abind_1.4-5 lifecycle_1.0.3 terra_1.7-29
## [52] stringi_1.7.12 leafsync_0.1.0 yaml_2.3.7
## [55] tmaptools_3.1-1 grid_4.2.2 parallel_4.2.2
## [58] crayon_1.5.2 deldir_1.0-9 stars_0.6-1
## [61] hms_1.1.3 knitr_1.43 pillar_1.9.0
## [64] markdown_1.7 codetools_0.2-18 stats4_4.2.2
## [67] wk_0.7.3 XML_3.99-0.14 glue_1.6.2
## [70] evaluate_0.21 leaflet.providers_1.9.0 latticeExtra_0.6-30
## [73] png_0.1-8 vctrs_0.6.2 tzdb_0.4.0
## [76] gtable_0.3.3 slippymath_0.3.1 cachem_1.0.8
## [79] xfun_0.39 mime_0.12 lwgeom_0.2-13
## [82] e1071_1.7-13 class_7.3-20 viridisLite_0.4.2
## [85] units_0.8-2 timechange_0.2.0 ellipsis_0.3.2