memory.limit(size = 16000) # Aumenta a 16 GB, si tienes esa RAM disponible
## Warning: 'memory.limit()' is no longer supported
## [1] Inf
Este cuaderno ilustra el cálculo de atributos geomorfométricos para el departamento de Nariño (Colombia), utilizando modelos digitales de elevación (DEM) en formato de cuadrícula. Su objetivo es introducir conceptos básicos de geomática aplicada a la agronomía.
Siguiendo el enfoque propuesto por el profesor, se empleará el paquete MultiscaleDTM de R para procesar datos topográficos. El análisis incluye:
-Cálculo de atributos primarios (pendiente, orientación).
-Generación de estadísticas zonales por municipios nariñenses.
-Visualización de la variabilidad topográfica característica de la región.
rm(list=ls())
# Cargar librerías necesarias
library(terra)
## terra 1.8.60
library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.0, PROJ 9.6.0; sf_use_s2() is TRUE
library(MultiscaleDTM)
library(exactextractr)
library(leaflet)
# Establecer directorio de trabajo
setwd("C:/Users/vocav/Documents/GB2-2025 nicolin-20250723T070234Z-1-001/GB2-2025 nicolin/GB2-2025/GB2/P5")
# Cargar archivos de entrada
# Se carga el modelo de elevación (DEM) y el archivo vectorial del departamento de Nariño. Estos son los datos base para el análisis de pendiente y orientación.
dem <- terra::rast("elev_Nariño_z10.tif")
narino <- sf::st_read("nariñito.gpkg")
## Reading layer `municipios' from data source
## `C:\Users\vocav\Documents\GB2-2025 nicolin-20250723T070234Z-1-001\GB2-2025 nicolin\GB2-2025\GB2\P5\nariñito.gpkg'
## using driver `GPKG'
## Simple feature collection with 64 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -79.01021 ymin: 0.3613481 xmax: -76.83368 ymax: 2.683898
## Geodetic CRS: MAGNA-SIRGAS
Recortamos el DEM usando los límites del departamento de Nariño para trabajar solo con esa zona.
dem2 <- terra::crop(dem, narino, mask = TRUE)
## Warning: [crop] CRS do not match
plot(dem2, main = "DEM recortado al departamento de Nariño")
#Proyectar a coordenadas planas (EPSG:9377)
# Transformamos los datos a una proyección en coordenadas planas para que los cálculos geométricos como pendiente y orientación sean más precisos.
dem_plane <- terra::project(dem2, "EPSG:9377")
narino_plane <- sf::st_transform(narino, "EPSG:9377")
plot(dem_plane, main = "DEM en coordenadas planas (EPSG:9377)")
# Calcular pendiente y orientación Se calcula asi dos variables
importantes del relieve: la pendiente (inclinación del terreno) y el
aspecto (orientación de la pendiente). Estos valores nos ayudan a
entender la forma del terreno en cada celda del raster.
slp_asp <- SlpAsp(
dem_plane,
w = c(3, 3),
unit = "degrees",
method = "queen",
metrics = c("slope", "aspect"),
na.rm = TRUE,
include_scale = FALSE,
mask_aspect = TRUE
)
slope <- subset(slp_asp, 1)
aspect <- subset(slp_asp, 2)
# 4.1 Visualización: histogramas
# El histograma de pendiente me muestra qué tan empinadas o planas son las zonas del territorio.El histograma de orientación me ayuda a ver hacia qué dirección cardinal (norte, sur, este, oeste) están orientadas las laderas.
#Pendiente (grados) - Nariño:La mayoría del terreno tiene pendientes suaves (0°-20°) con frecuencias altas (hasta 100,000), mientras que pendientes pronunciadas (40°-60°) son poco comunes, lo que indica un relieve predominantemente plano a moderado.
#Orientación (aspecto) - Nariño:Algunas orientaciones (ej. 0°, 10°, 20°) muestran frecuencias elevadas (hasta 15,000), pero no hay una dirección dominante clara, sugiriendo una distribución relativamente variada en las laderas
terra::hist(slope, main = "Pendiente (grados) - Nariño", col = "dodgerblue4", xlab = "Grados")
## Warning: [hist] a sample of 9% of the cells was used (of which 50% was NA)
terra::hist(aspect, main = "Orientación (aspect) - Nariño", col = "darkmagenta", xlab = "Grados")
## Warning: [hist] a sample of 9% of the cells was used (of which 50% was NA)
# Conversión de pendiente a porcentaje y reclasificación IGAC
Convertimos la pendiente de grados a porcentaje, que es una forma más
intuitiva para interpretar la inclinación del terreno.
slope_perc <- tan(slope * (pi/180)) * 100
terra::hist(slope_perc, main = "Pendiente (%) - Nariño", xlab = "Porcentaje", col = "darkorange3")
## Warning: [hist] a sample of 9% of the cells was used (of which 50% was NA)
m <- matrix(c(
0, 3, 1,
3, 7, 2,
7, 12, 3,
12, 25, 4,
25, 50, 5,
50, 75, 6,
75, 160, 7
), ncol = 3, byrow = TRUE)
rc <- terra::classify(slope_perc, m, right = TRUE)
Extraemos estadísticas por municipio: la pendiente promedio y la clase de pendiente más frecuente. Estas estadísticas son útiles para entender el relieve dominante en cada municipio.
narino_plane$mean_slope <- exact_extract(slope_perc, narino_plane, 'mean')
## | | | 0% | |= | 2% | |== | 3% | |=== | 5% | |==== | 6% | |===== | 8% | |======= | 9% | |======== | 11% | |========= | 12% | |========== | 14% | |=========== | 16% | |============ | 17% | |============= | 19% | |============== | 20% | |=============== | 22% | |================ | 23% | |================== | 25% | |=================== | 27% | |==================== | 28% | |===================== | 30% | |====================== | 31% | |======================= | 33% | |======================== | 34% | |========================= | 36% | |========================== | 38% | |=========================== | 39% | |============================ | 41% | |============================== | 42% | |=============================== | 44% | |================================ | 45% | |================================= | 47% | |================================== | 48% | |=================================== | 50% | |==================================== | 52% | |===================================== | 53% | |====================================== | 55% | |======================================= | 56% | |======================================== | 58% | |========================================== | 59% | |=========================================== | 61% | |============================================ | 62% | |============================================= | 64% | |============================================== | 66% | |=============================================== | 67% | |================================================ | 69% | |================================================= | 70% | |================================================== | 72% | |=================================================== | 73% | |==================================================== | 75% | |====================================================== | 77% | |======================================================= | 78% | |======================================================== | 80% | |========================================================= | 81% | |========================================================== | 83% | |=========================================================== | 84% | |============================================================ | 86% | |============================================================= | 88% | |============================================================== | 89% | |=============================================================== | 91% | |================================================================= | 92% | |================================================================== | 94% | |=================================================================== | 95% | |==================================================================== | 97% | |===================================================================== | 98% | |======================================================================| 100%
hist(narino_plane$mean_slope, main = "Pendiente promedio por municipio (Nariño)",
xlab = "Pendiente (%)", col = "steelblue")
narino_plane$class <- exact_extract(rc, narino_plane, 'mode')
## | | | 0% | |= | 2% | |== | 3% | |=== | 5% | |==== | 6% | |===== | 8% | |======= | 9% | |======== | 11% | |========= | 12% | |========== | 14% | |=========== | 16% | |============ | 17% | |============= | 19% | |============== | 20% | |=============== | 22% | |================ | 23% | |================== | 25% | |=================== | 27% | |==================== | 28% | |===================== | 30% | |====================== | 31% | |======================= | 33% | |======================== | 34% | |========================= | 36% | |========================== | 38% | |=========================== | 39% | |============================ | 41% | |============================== | 42% | |=============================== | 44% | |================================ | 45% | |================================= | 47% | |================================== | 48% | |=================================== | 50% | |==================================== | 52% | |===================================== | 53% | |====================================== | 55% | |======================================= | 56% | |======================================== | 58% | |========================================== | 59% | |=========================================== | 61% | |============================================ | 62% | |============================================= | 64% | |============================================== | 66% | |=============================================== | 67% | |================================================ | 69% | |================================================= | 70% | |================================================== | 72% | |=================================================== | 73% | |==================================================== | 75% | |====================================================== | 77% | |======================================================= | 78% | |======================================================== | 80% | |========================================================= | 81% | |========================================================== | 83% | |=========================================================== | 84% | |============================================================ | 86% | |============================================================= | 88% | |============================================================== | 89% | |=============================================================== | 91% | |================================================================= | 92% | |================================================================== | 94% | |=================================================================== | 95% | |==================================================================== | 97% | |===================================================================== | 98% | |======================================================================| 100%
hist(narino_plane$class, main = "Clase de pendiente dominante por municipio",
xlab = "Clase IGAC", col = "forestgreen")
Transformamos los datos nuevamente a coordenadas geográficas (EPSG:4326) para poder visualizarlos con leaflet, que necesita esta proyección.
#Proyección a EPSG:4326
rc_geo <- terra::project(rc, "EPSG:4326")
slope_geo <- terra::project(slope_perc, "EPSG:4326")
slope_geo_reduced <- terra::aggregate(slope_geo, fact = 2, fun = "mean")
## |---------|---------|---------|---------|=========================================
# 7.1 Mapa: Pendiente (%)
# Ahora generamos un mapa donde se muestra la pendiente en porcentaje. Es interactivo, así que puedo acercarme a cualquier zona del departamento para explorar su relieve.
pal_slope <- colorNumeric(
c("#ffffb2", "#fecc5c", "#fd8d3c", "#e31a1c", "#800026"),
values(slope_geo_reduced),
na.color = "transparent"
)
leaflet(narino) %>%
addTiles() %>%
setView(lng = -77.5, lat = 1.5, zoom = 8) %>%
addPolygons(
data = narino,
color = "gray", weight = 1.0, smoothFactor = 0.5,
opacity = 0.4, fillOpacity = 0.1,
popup = paste("Clase pendiente: ", narino_plane$class)
) %>%
addRasterImage(slope_geo_reduced, colors = pal_slope, opacity = 0.8) %>%
addLegend(pal = pal_slope, values = values(slope_geo_reduced),
title = "Pendiente (%) - Nariño")
## Warning: sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs).
## Need '+proj=longlat +datum=WGS84'