title: “Interpolacion Espacial del carbono organico del suelo en Meta”
author: “Nawel Sebastian Ballesteros Sierra”
date: 13/11/2025
##1.Introduccion
Este cuaderno muestra cómo dos métodos de interpolación—Inverse Distance Weighting (IDW) y Kriging Ordinario (OK)—permiten transformar datos puntuales de carbono orgánico del suelo (SOC) en superficies continuas. Usando información de SoilGrids (15–30 cm), se ilustra la diferencia entre un método basado únicamente en la distancia (IDW) y uno que incorpora la estructura espacial del fenómeno (OK).
##2.Configuracones
Limpiar el entorno
Elimina todos los objetos cargados en la sesión para evitar errores con variables viejas.
rm(list=ls())
Carga de librerías
Estas librerías permiten: terra / sf / sp / stars → trabajar con datos espaciales (raster y vector). gstat / automap → realizar interpolaciones (IDW, Kriging). leaflet / leafem → crear mapas interactivos. RColorBrewer → generar paletas de colores.
library(terra)
## Warning: package 'terra' was built under R version 4.5.2
## terra 1.8.86
library(sf)
## Warning: package 'sf' was built under R version 4.5.2
## Linking to GEOS 3.13.1, GDAL 3.11.4, PROJ 9.7.0; sf_use_s2() is TRUE
library(sp)
## Warning: package 'sp' was built under R version 4.5.2
library(stars)
## Warning: package 'stars' was built under R version 4.5.2
## Cargando paquete requerido: abind
## Warning: package 'abind' was built under R version 4.5.2
library(gstat)
## Warning: package 'gstat' was built under R version 4.5.2
library(automap)
## Warning: package 'automap' was built under R version 4.5.2
library(RColorBrewer)
## Warning: package 'RColorBrewer' was built under R version 4.5.2
library(leaflet)
## Warning: package 'leaflet' was built under R version 4.5.2
library(leafem)
## Warning: package 'leafem' was built under R version 4.5.2
##3.Cargar archivos
Revisar si existe el archivo de municipios en la carpeta data.
list.files(path="data", pattern = "metamunicipios.gpkg")
## [1] "metamunicipios.gpkg"
Se carga los puntos con el valor de SOC (carbono orgánico del suelo).
samples <- sf::st_read("data/soc_meta.gpkg")
## Reading layer `soc_meta' from data source
## `C:\Users\nawel\Downloads\GB2\Proyecto 6\data\soc_meta.gpkg'
## using driver `GPKG'
## Simple feature collection with 1947 features and 1 field
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: -74.93382 ymin: 1.570154 xmax: -71.03937 ymax: 4.861022
## Geodetic CRS: +proj=longlat +datum=WGS84 +no_defs
Se carga el mapa de municipios del Meta.
munic <- sf::st_read("data/metamunicipios.gpkg")
## Reading layer `MetaMunicipios' from data source
## `C:\Users\nawel\Downloads\GB2\Proyecto 6\data\metamunicipios.gpkg'
## using driver `GPKG'
## Simple feature collection with 29 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -74.9206 ymin: 1.570401 xmax: -71.0749 ymax: 4.860201
## Geodetic CRS: WGS 84
##4.Revisar y explorar los datos
summary(): estadísticas descriptivas del SOC.
summary(samples)
## soc geom
## Min. : 8.525 POINT :1947
## 1st Qu.:12.215 epsg:NA : 0
## Median :15.183 +proj=long...: 0
## Mean :20.770
## 3rd Qu.:20.957
## Max. :82.989
hist(): histograma de la distribución del SOC.
hist(samples$soc)
round(): redondea los valores a 2 decimales.
samples$soc = round(samples$soc,2)
Se crea una paleta de colores para Leaflet donde se define los colores que representarán los valores de SOC.
pal <- colorNumeric(
c("#E1F5C4", "#EDE574", "#F9D423", "#FC913A", "#FF4E50"),
# colors depend on the count variable
domain = samples$soc,
)
Mapa interactivo de puntos en los que se muestra: polígonos de municipios, puntos con valor SOC,leyenda,fondo de OpenStreetMap
leaflet() %>%
addPolygons(
data = munic,
color = "gray",
# set the opacity of the outline
opacity = 1,
# set the stroke width in pixels
weight = 1,
# set the fill opacity
fillOpacity = 0.2) %>%
addCircleMarkers(
data = samples,
radius= 1.5,
label = ~soc,
color = ~pal(soc),
fillOpacity = 1,
stroke = F
) %>%
addLegend(
data = samples,
pal = pal,
values = ~soc,
position = "bottomleft",
title = "SOC:",
opacity = 0.9) %>%
addProviderTiles("OpenStreetMap")
##5.Interpolaciones
Se le indica a gstat que queremos interpolar la variable soc sin variables auxiliares.
g1 = gstat(formula = soc ~ 1, data = samples)
Se carga el raster de altitud del departamento del meta para generar una malla donde se puedan interpolar los datos
dem <- terra::rast("rastermeta.tif")
Crear el raster vacío donde se interpolará
Este raster define: área de interpolación (coordenadas de meta),dimensiones(resolución),sistema de referencia El valor “1” es solo de relleno.
(rrr <- terra::rast(xmin=-74.9, xmax=-71.1, ymin=1.62, ymax=4.91, nrows=370, ncols = 329, vals = 1, crs = "epsg:4326"))
## class : SpatRaster
## size : 370, 329, 1 (nrow, ncol, nlyr)
## resolution : 0.01155015, 0.008891892 (x, y)
## extent : -74.9, -71.1, 1.62, 4.91 (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326)
## source(s) : memory
## name : lyr.1
## min value : 1
## max value : 1
Convertir raster a formato STARS es necesario porque gstat trabaja con STARS para predicción.
stars.rrr <- stars::st_as_stars(rrr)
Se hace una Interpolación IDW al generar un raster interpolado
z1 = predict(g1, stars.rrr)
## [inverse distance weighted interpolation]
se verifica que es Z1
z1
## stars object with 2 dimensions and 2 attributes
## attribute(s):
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## var1.pred 8.605225 13.93298 16.14701 20.74495 21.65034 82.4907 0
## var1.var NA NA NA NaN NA NA 121730
## dimension(s):
## from to offset delta refsys x/y
## x 1 329 -74.9 0.01155 WGS 84 [x]
## y 1 370 4.91 -0.008892 WGS 84 [y]
Rellenando valores NA ya que algunos no tendran valores por lo cual Los huecos sin datos los reemplaza por 0.
a <- which(is.na(z1[[1]]))
z1[[1]][a] = 0.0
Nuevamente se verifica si estamos trabajando con Z1
z1
## stars object with 2 dimensions and 2 attributes
## attribute(s):
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## var1.pred 8.605225 13.93298 16.14701 20.74495 21.65034 82.4907 0
## var1.var NA NA NA NaN NA NA 121730
## dimension(s):
## from to offset delta refsys x/y
## x 1 329 -74.9 0.01155 WGS 84 [x]
## y 1 370 4.91 -0.008892 WGS 84 [y]
se asigna el nombre a z1 por soc
names(z1) = "soc"
se genera la paleta de colores y
paleta <- colorNumeric(palette = c("orange", "yellow", "cyan", "green"), domain = 10:120, na.color = "transparent")
Se agrega el raster interpolado al mapa Leaflet con raster IDW
m <- leaflet() %>%
addTiles() %>%
leafem:::addGeoRaster(
z1,
opacity = 0.7,
colorOptions = colorOptions(palette = c("orange", "yellow", "cyan", "green"),
domain = 10:100)
) %>%
addCircleMarkers(
data = samples,
radius= 1.5,
label = ~soc,
color = ~paleta(soc),
fillOpacity = 1,
stroke = F
) %>%
addLegend("bottomright", pal=paleta, values= z1$soc,
title = "IDW SOC interpolation [%]"
)
## Warning in pal(c(r[1], cuts, r[2])): Some values were outside the color scale
## and will be treated as NA
## Warning in paleta(soc): Some values were outside the color scale and will be
## treated as NA
## Warning in paleta(soc): Some values were outside the color scale and will be
## treated as NA
## Warning in write_stars.stars(x, dsn = fl): all but first attribute are ignored
m
Variograma empírico
Analiza la autocorrelación espacial del SOC.
v_emp_ok = variogram(soc ~ 1, data=samples)
generar el diagrama
plot(v_emp_ok)
Ajuste automático del variograma
Encuentra el mejor modelo teórico (Spherical, Exponential, etc.).
v_mod_ok = automap::autofitVariogram(soc ~ 1, as(samples, "Spatial"))
Genera el variograma teorico
plot(v_mod_ok)
v_mod_ok$var_model
## model psill range kappa
## 1 Nug 10.69485 0.0000 0.0
## 2 Ste 281.31428 264.5914 0.4
Crea el modelo gstat con variograma
g2 = gstat(formula = soc ~ 1, model = v_mod_ok$var_model, data = samples)
z2= predict(g2, stars.rrr)
## [using ordinary kriging]
Rellena valores NA los huecos sin datos los reemplaza por 0.
a <- which(is.na(z2[[1]]))
z2[[1]][a] = 0.0
names(z2) = "soc"
Mapa Leaflet con Kriging
Igual que con IDW, pero usando z2.
m <- leaflet() %>%
addTiles() %>%
leafem:::addGeoRaster(
z2,
opacity = 0.7,
colorOptions = colorOptions(palette = c("orange", "yellow", "cyan", "green"),
domain = 10:100)
) %>%
addCircleMarkers(
data = samples,
radius= 1.5,
label = ~soc,
color = ~paleta(soc),
fillOpacity = 1,
stroke = F
) %>%
addLegend("bottomright", pal = paleta, values= z2$soc,
title = "OK SOC interpolation [%]"
)
## Warning in pal(c(r[1], cuts, r[2])): Some values were outside the color scale
## and will be treated as NA
## Warning in paleta(soc): Some values were outside the color scale and will be
## treated as NA
## Warning in paleta(soc): Some values were outside the color scale and will be
## treated as NA
## Warning in write_stars.stars(x, dsn = fl): all but first attribute are ignored
m
colores <- colorOptions(palette = c("orange", "yellow", "cyan", "green"), domain = 10:100, na.color = "transparent")
Comparación de IDW y Kriging con controles de capasy permite activar y desactivar cada raster.
m <- leaflet() %>%
addTiles() %>%
addGeoRaster(z1, colorOptions = colores, opacity = 0.8, group= "IDW") %>%
addGeoRaster(z2, colorOptions = colores, opacity = 0.8, group= "OK") %>%
# Add layers controls
addLayersControl(
overlayGroups = c("IDW", "OK"),
options = layersControlOptions(collapsed = FALSE)
) %>%
addLegend("bottomright", pal = paleta, values= z1$soc,
title = "Soil organic carbon [%]"
)
## Warning in pal(c(r[1], cuts, r[2])): Some values were outside the color scale
## and will be treated as NA
## Warning in write_stars.stars(x, dsn = fl): all but first attribute are ignored
## Warning in write_stars.stars(x, dsn = fl): all but first attribute are ignored
Generamos el mapa comparativo entre IDW Y Kriking
m
Exportar los resultados
Guardamos los raster interpolados en archivos TIFF.
write_stars(
z1, dsn = "data/IDW_soc_stder.tif", layer = 1
)
write_stars(
z2, dsn = "data/OK_soc_stder.tif", layer = 1
)
Una vez calculados ambos valores RMSE, compárelos y analice sus diferencias. ¿Cuál es el método de interpolación más fiable? Explique.
En interpolación espacial, el RMSE (Root Mean Square Error) mide la diferencia entre los valores observados y los estimados por cada modelo. Es decir:
RMSE alto → peor precisión RMSE bajo → mejor precisión
El método más fiable es el que presente menor RMSE, y en la mayoría de casos es Kriging, porque modela explícitamente la autocorrelación espacial y produce estimaciones óptimas.
##8.Conclusiones
En este cuaderno se realizó un flujo completo de análisis geoestadístico para estimar el SOC en el Meta, desde la carga y exploración de datos hasta la creación de mapas interactivos y la generación de interpolaciones. Se aplicaron y compararon dos métodos, IDW y Kriging Ordinario, entendiendo sus diferencias y la importancia del variograma en la modelación espacial. La comparación permitió identificar que Kriging suele ofrecer resultados más consistentes al incorporar la autocorrelación espacial. Finalmente, se exportaron los productos interpolados, logrando una comprensión general del proceso de interpolación aplicado a datos ambientales.
##9.Referencias
Tomado desde
Lizarazo, I. 2025. Spatial interpolation. Available at: https://rpubs.com/ials2un/Spatial_Interpolation
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=Spanish_Latin America.utf8
## [2] LC_CTYPE=Spanish_Latin America.utf8
## [3] LC_MONETARY=Spanish_Latin America.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=Spanish_Latin America.utf8
##
## time zone: America/Bogota
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] leafem_0.2.5 leaflet_2.2.3 RColorBrewer_1.1-3 automap_1.1-20
## [5] gstat_2.1-4 stars_0.6-8 abind_1.4-8 sp_2.2-0
## [9] sf_1.0-21 terra_1.8-86
##
## loaded via a namespace (and not attached):
## [1] generics_0.1.4 sass_0.4.10 class_7.3-23
## [4] KernSmooth_2.23-26 lattice_0.22-7 digest_0.6.37
## [7] magrittr_2.0.4 evaluate_1.0.5 grid_4.5.1
## [10] fastmap_1.2.0 plyr_1.8.9 jsonlite_2.0.0
## [13] e1071_1.7-16 reshape_0.8.10 DBI_1.2.3
## [16] crosstalk_1.2.2 scales_1.4.0 codetools_0.2-20
## [19] jquerylib_0.1.4 cli_3.6.5 rlang_1.1.6
## [22] units_1.0-0 intervals_0.15.5 base64enc_0.1-3
## [25] cachem_1.1.0 FNN_1.1.4.1 raster_3.6-32
## [28] tools_4.5.1 parallel_4.5.1 dplyr_1.1.4
## [31] ggplot2_4.0.0 spacetime_1.3-3 png_0.1-8
## [34] vctrs_0.6.5 R6_2.6.1 zoo_1.8-14
## [37] proxy_0.4-27 lifecycle_1.0.4 classInt_0.4-11
## [40] leaflet.providers_2.0.0 htmlwidgets_1.6.4 pkgconfig_2.0.3
## [43] pillar_1.11.1 bslib_0.9.0 gtable_0.3.6
## [46] glue_1.8.0 Rcpp_1.1.0 tidyselect_1.2.1
## [49] tibble_3.3.0 xfun_0.54 rstudioapi_0.17.1
## [52] knitr_1.50 farver_2.1.2 htmltools_0.5.8.1
## [55] rmarkdown_2.30 xts_0.14.1 compiler_4.5.1
## [58] S7_0.2.0