# library
lapply(c(
"sf", "readxl", "dplyr", "stringr", "summarytools",
"gstat", "RColorBrewer", "mapview", "leafsync", "kableExtra"
), library, character.only = TRUE)
Definición del problema objeto de estudio
El objetivo central de este análisis es comprender la variabilidad
espacial de la temperatura registrada en las ubicaciones de
árboles de aguacate en el Cauca, Colombia, a partir de
datos georreferenciados recolectados en una jornada puntual de monitoreo
(01/10/2020). Este ejercicio busca identificar patrones espaciales que
permitan modelar la dependencia entre observaciones y fundamentar
posteriores procesos de interpolación espacial, clave para
apoyar la toma de decisiones agrícolas y la planificación de cultivos en
el territorio.
# data
df_aguacate <- readxl::read_excel("Data/Datos_Completos_Aguacate.xlsx") %>%
mutate(Fecha = str_extract(FORMATTED_DATE_TIME, "^\\d{1,2}/\\d{1,2}/\\d{4}")) %>%
filter(Fecha == "01/10/2020")
Exploración y visualización de los datos
Se trabajó con un conjunto de datos provenientes del monitoreo de
distintas variables en 494 árboles de aguacate de la
Finca Guadalupe Hass, ubicada en El Tambo, Cauca. Entre las
variables registradas a lo largo de varios años, para este análisis se
seleccionó la temperatura correspondiente al periodo de
muestreo más reciente, fechado el 01/10/2020. El resumen
estadístico muestra que la temperatura media registrada durante este
periodo fue de 25.8 °C con una desviación estándar de
1.8 °C. Los valores observados oscilaron entre
22.2 °C y 29.7 °C, con una mediana de
25.8 °C y un rango intercuartílico de
2.7 °C.
Resumen de variables registradas por ubicación de árboles de aguacate
| Variable |
Stats / Values |
Freqs (% of Valid) |
Graph |
Missing |
| id_arbol
[character] |
| 1. 1 | | 2. 10 | | 3. 100 | | 4. 101 | | 5. 102 | | 6. 103 | | 7. 104 | | 8. 105 | | 9. 106 | | 10. 107 | | [ 524 others ] |
|
| 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 1 | ( | 0.2% | ) | | 524 | ( | 98.1% | ) |
|
 |
0
(0.0%) |
| Latitude
[numeric] |
| Mean (sd) : 2.4 (0) | | min ≤ med ≤ max: | | 2.4 ≤ 2.4 ≤ 2.4 | | IQR (CV) : 0 (0) |
|
447 distinct values |
 |
0
(0.0%) |
| Longitude
[numeric] |
| Mean (sd) : -76.7 (0) | | min ≤ med ≤ max: | | -76.7 ≤ -76.7 ≤ -76.7 | | IQR (CV) : 0 (0) |
|
451 distinct values |
 |
0
(0.0%) |
| FORMATTED_DATE_TIME
[character] |
1. 01/10/2020 10:11:12 a, m |
|
 |
0
(0.0%) |
| Psychro_Wet_Bulb_Temperature
[numeric] |
| Mean (sd) : 21.6 (1.1) | | min ≤ med ≤ max: | | 19 ≤ 21.5 ≤ 24.9 | | IQR (CV) : 1.6 (0.1) |
|
57 distinct values |
 |
0
(0.0%) |
| Station_Pressure
[numeric] |
| Mean (sd) : 825.5 (1.1) | | min ≤ med ≤ max: | | 822.4 ≤ 825.7 ≤ 827.4 | | IQR (CV) : 1.7 (0) |
|
50 distinct values |
 |
0
(0.0%) |
| Relative_Humidity
[numeric] |
| Mean (sd) : 71.2 (5.3) | | min ≤ med ≤ max: | | 59.5 ≤ 71.2 ≤ 91.6 | | IQR (CV) : 8 (0.1) |
|
200 distinct values |
 |
0
(0.0%) |
| Crosswind
[numeric] |
| Mean (sd) : 0.2 (0.2) | | min ≤ med ≤ max: | | 0 ≤ 0.1 ≤ 1.5 | | IQR (CV) : 0.4 (1.2) |
|
13 distinct values |
 |
0
(0.0%) |
| Temperature
[numeric] |
| Mean (sd) : 25.8 (1.8) | | min ≤ med ≤ max: | | 22.2 ≤ 25.8 ≤ 29.7 | | IQR (CV) : 2.7 (0.1) |
|
75 distinct values |
 |
0
(0.0%) |
| Barometric_Pressure
[numeric] |
| Mean (sd) : 825.5 (1.1) | | min ≤ med ≤ max: | | 822.4 ≤ 825.7 ≤ 827.4 | | IQR (CV) : 1.8 (0) |
|
31 distinct values |
 |
0
(0.0%) |
| Headwind
[numeric] |
| Mean (sd) : 0.2 (0.3) | | min ≤ med ≤ max: | | -0.7 ≤ 0.1 ≤ 1.3 | | IQR (CV) : 0.4 (1.6) |
|
20 distinct values |
 |
0
(0.0%) |
| Direction_True
[numeric] |
| Mean (sd) : 222.5 (125.4) | | min ≤ med ≤ max: | | 0 ≤ 287.5 ≤ 359 | | IQR (CV) : 245.8 (0.6) |
|
198 distinct values |
 |
0
(0.0%) |
| Direction_Mag
[numeric] |
| Mean (sd) : 223.3 (125) | | min ≤ med ≤ max: | | 0 ≤ 287.5 ≤ 359 | | IQR (CV) : 246 (0.6) |
|
203 distinct values |
 |
0
(0.0%) |
| Wind_Speed
[numeric] |
| Mean (sd) : 0.3 (0.3) | | min ≤ med ≤ max: | | 0 ≤ 0.4 ≤ 1.8 | | IQR (CV) : 0.5 (1) |
|
15 distinct values |
 |
0
(0.0%) |
| Heat_Stress_Index
[numeric] |
| Mean (sd) : 27.4 (2.6) | | min ≤ med ≤ max: | | 22.8 ≤ 27.2 ≤ 34.5 | | IQR (CV) : 4 (0.1) |
|
107 distinct values |
 |
0
(0.0%) |
| Altitude
[numeric] |
| Mean (sd) : 1693 (11) | | min ≤ med ≤ max: | | 1675 ≤ 1692 ≤ 1724 | | IQR (CV) : 15.8 (0) |
|
47 distinct values |
 |
0
(0.0%) |
| Dew_Point
[numeric] |
| Mean (sd) : 20.2 (1.1) | | min ≤ med ≤ max: | | 17.7 ≤ 20 ≤ 24 | | IQR (CV) : 1.4 (0.1) |
|
58 distinct values |
 |
0
(0.0%) |
| Density_Altitude
[numeric] |
| Mean (sd) : 2.6 (0.1) | | min ≤ med ≤ max: | | 2.4 ≤ 2.6 ≤ 2.7 | | IQR (CV) : 0.1 (0) |
|
224 distinct values |
 |
0
(0.0%) |
| Wind_Chill
[numeric] |
| Mean (sd) : 25.8 (1.8) | | min ≤ med ≤ max: | | 22.2 ≤ 25.8 ≤ 29.6 | | IQR (CV) : 2.6 (0.1) |
|
74 distinct values |
 |
0
(0.0%) |
| Estado_Fenologico_Predominante
[numeric] |
| Mean (sd) : 717.8 (0.5) | | min ≤ med ≤ max: | | 717 ≤ 718 ≤ 719 | | IQR (CV) : 1 (0) |
|
| 717 | : | 147 | ( | 27.5% | ) | | 718 | : | 369 | ( | 69.1% | ) | | 719 | : | 18 | ( | 3.4% | ) |
|
 |
0
(0.0%) |
| Frutos_Afectados
[numeric] |
|
|
 |
0
(0.0%) |
| Fecha
[character] |
1. 01/10/2020 |
|
 |
0
(0.0%) |
La visualización espacial de estos datos, realizada mediante la
función mapview(), permitió identificar una
distribución heterogénea de la temperatura en el área de
estudio. El mapa evidencia la presencia de gradientes térmicos y
posibles agrupamientos de valores elevados y bajos en distintas zonas
del lote, lo que justifica la exploración posterior de autocorrelación y
dependencia espacial de la variable. Este análisis visual resulta
fundamental para orientar el ajuste de modelos de variograma y la
aplicación de técnicas de interpolación espacial.
aguacate_sf <- st_as_sf(df_aguacate,
coords = c("Longitude", "Latitude"),
crs = 4326)
cat('<h5>`Valores de temperatura en ubicaciones de los árboles de aguacate`</h5>')
Valores de temperatura en ubicaciones de los árboles de aguacate
maptemp <-mapview(
aguacate_sf,
zcol = "Temperature",
layer.name = "Temperatura [°C]",
cex = 4,
alpha = 0,
col.regions = colorRampPalette(brewer.pal(9, "YlOrRd")),
legend = TRUE
)
maptemp
Construcción y análisis del variograma muestral
La estructura espacial de la temperatura se exploró mediante la
construcción de la nube de variograma y el
variograma muestral, utilizando la función
variogram() del paquete gstat. La nube de
variograma representa la dispersión de las diferencias cuadráticas de
temperatura entre todos los pares de puntos según su distancia, mientras
que el variograma muestral agrupa estas diferencias en intervalos,
mostrando la relación promedio entre semivarianza y distancia.
La interpretación del variograma muestral indica un
incremento inicial de la semivarianza con la distancia,
hasta alcanzar una meseta en torno a los 2.5 a 3.0 °C² para
distancias superiores a 50 metros. El valor de
nugget, que representa la variabilidad no explicada a
escalas menores al muestreo o debida a error de medición, fue estimado
en 1.0 a 1.5 °C². El rango espacial, definido
como la distancia a partir de la cual la semivarianza se estabiliza y la
autocorrelación espacial deja de ser significativa, fue identificado en
aproximadamente 50 metros.
aguacate_sf <- st_transform(aguacate_sf, crs = 32618)
cat('<h5>`Nube de variograma (cloud)`</h5>')
Nube de variograma (cloud)
# Variograma cloud
plot(variogram(Temperature ~ 1, data = aguacate_sf, cloud = TRUE))

cat('<h5>`Variograma muestral`</h5>')
Variograma muestral
# Variograma muestral
v <- variogram(Temperature ~ 1, data = aguacate_sf)
plot(v)

Ajuste y comparación de modelos de variograma
Para describir la estructura espacial observada en la temperatura, se
ajustaron varios modelos teóricos de variograma utilizando la función
fit.variogram() del paquete gstat. Se
emplearon como parámetros iniciales los valores extraídos del variograma
muestral: nugget ≈ 1.25, sill ≈ 2.75 y
range ≈ 50. Los modelos evaluados incluyeron el
exponencial,
esférico,
gaussiano,
lineal,
circular y
pentasférico. El ajuste de cada modelo se
evaluó mediante el error cuadrático de ajuste (SSErr).
cat('<h4>`Ajuste de modelos de variograma`</h4>')
Ajuste de modelos de variograma
mod <- c("Exp", "Sph", "Gau", "Lin", "Cir", "Pen")
mod_titulos <- c("Exponencial", "Esférico", "Gaussiano", "Linear", "Circular", "Pentasférico")
fits <- lapply(mod, function(m)
fit.variogram(v, vgm(psill = 2.75, model = m, range = 50, nugget = 1.25))
)
cat('<h5>`Modelo Exponencial`</h5>')
Modelo Exponencial
plot(v, model = fits[[1]])

cat('<h5>`Modelo Esférico`</h5>')
Modelo Esférico
plot(v, model = fits[[2]])

cat('<h5>`Modelo Gaussiano`</h5>')
Modelo Gaussiano
plot(v, model = fits[[3]])

cat('<h5>`Modelo Linear`</h5>')
Modelo Linear
plot(v, model = fits[[4]])

cat('<h5>`Modelo Circular`</h5>')
Modelo Circular
plot(v, model = fits[[5]])

cat('<h5>`Modelo Pentasférico`</h5>')
Modelo Pentasférico
plot(v, model = fits[[6]])

El modelo pentasférico presentó el
menor error de ajuste (SSErr = 1.03540), seguido por el
esférico (SSErr = 1.05537) y el circular
(SSErr = 1.07545), lo que indica que estos modelos
representan mejor la estructura espacial de la temperatura en el área de
estudio. Por el contrario, el modelo gaussiano presentó un error
considerablemente mayor (SSErr = 3.28096), reflejando un
ajuste deficiente.
Estos resultados, sumados a la inspección visual de los ajustes sobre
el variograma muestral, respaldan la selección del modelo pentasférico
como el más adecuado para describir la dependencia espacial de la
variable temperatura en el lote evaluado.
par(mfrow = c(1, 1))
#erros
ss_err <- sapply(fits, function(fit) attr(fit, "SSErr"))
# param
params <- do.call(rbind, lapply(fits, function(x) x[2, c("psill", "range", "model")]))
nugget <- sapply(fits, function(x) x[1, "psill"])
tbl <- tibble::tibble(
Model = mod_titulos,
Nugget = round(nugget, 3),
Sill = round(params[, "psill"], 3),
Range = round(params[, "range"], 3),
SSErr = round(ss_err, 5)
)
# best model
min_row <- which.min(tbl$SSErr)
tbl$Model[min_row] <- paste0("**", tbl$Model[min_row], "**")
cat('<h5>`Resumen de ajuste de modelos de variograma`</h5>')
Resumen de ajuste de modelos de variograma
tbl %>%
kable(align = "lrrrr") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
|
Model
|
Nugget
|
Sill
|
Range
|
SSErr
|
|
Exponencial
|
0.437
|
2.636
|
13.578
|
1.11254
|
|
Esférico
|
0.753
|
2.150
|
30.806
|
1.05537
|
|
Gaussiano
|
1.015
|
1.909
|
12.341
|
3.28096
|
|
Linear
|
0.922
|
1.979
|
24.593
|
1.36529
|
|
Circular
|
0.792
|
2.103
|
27.218
|
1.07545
|
|
Pentasférico
|
0.725
|
2.194
|
37.524
|
1.03540
|
Interpolación espacial mediante Kriging
La interpolación de la temperatura en áreas no muestreadas se realizó
mediante el método de kriging, utilizando el
modelo de variograma pentasférico previamente ajustado.
Este procedimiento se implementó con la función
gstat::gstat() para definir el objeto de kriging, seguido
de predict() para obtener las predicciones sobre una grilla
regular abarcando el área de muestreo. Las predicciones resultantes
fueron posteriormente recortadas al polígono definido por el convex
hull de los puntos observados, con el fin de evitar extrapolaciones
fuera del dominio real de los datos.
# Kriging
fit_pen <- fit.variogram(v, model = vgm(psill = 2.75,
model = "Pen", range = 50, nugget = 1.25))
k <- gstat(formula = Temperature ~ 1, data = aguacate_sf, model = fit_pen)
# grid
bbox <- st_bbox(aguacate_sf)
grd <- expand.grid(
x = seq(bbox["xmin"], bbox["xmax"], length.out = 150),
y = seq(bbox["ymin"], bbox["ymax"], length.out = 150)
)
grd_sf <- st_as_sf(grd, coords = c("x", "y"), crs = st_crs(aguacate_sf))
# prediction
kpred <- predict(k, newdata = grd_sf)
La comparación entre el mapa de temperaturas observadas y el mapa de
predicción obtenida por kriging, visualizados de manera sincronizada con
leafsync::sync(), evidencia una notable similitud en los
patrones espaciales identificados. Ambas visualizaciones muestran la
presencia de gradientes térmicos y agrupamientos de valores
altos y bajos en regiones coincidentes dentro del lote, lo que indica
que el modelo de kriging ha capturado adecuadamente la estructura
espacial de la variable temperatura. Esto evidencia que el modelo
ajustado logra capturar adecuadamente la dependencia espacial de la
variable. Además, la calidad predictiva del modelo se evaluó mediante
validación cruzada tipo leave-one-out, obteniendo un error
cuadrático medio (RMSE) de 1.07 °C, un error
absoluto medio (MAE) de 0.84 °C y un error
medio (ME) cercano a cero (-0.006 °C). Estos
resultados cuantitativos respaldan la robustez y ausencia de sesgo
relevante en las predicciones generadas
# convex hull
hull <- st_convex_hull(st_union(aguacate_sf))
kpred_cropped <- kpred[st_within(st_geometry(kpred), hull, sparse = FALSE), ]
# map pred
map_krig <- mapview(
kpred_cropped,
zcol = "var1.pred",
layer.name = "Predicción kriging [°C]",
col.regions = colorRampPalette(brewer.pal(9, "YlOrRd")),
legend = TRUE,
alpha = 0
)
# maps
cat('<h5>`Comparación: temperaturas observadas y predicción espacial por kriging`</h5>')
Comparación: temperaturas observadas y predicción espacial por kriging
leafsync::sync(maptemp, map_krig)
# leave-one-out (LOOCV)
cv <- krige.cv(Temperature ~ 1, locations = aguacate_sf, model = fit_pen, nfold = nrow(aguacate_sf))
# tbl
cv_summary <- tibble::tibble(
RMSE = sqrt(mean(cv$residual^2, na.rm = TRUE)),
MAE = mean(abs(cv$residual), na.rm = TRUE),
ME = mean(cv$residual, na.rm = TRUE)
)
cat('<h5>`Resultados de validación cruzada (LOOCV) para kriging`</h5>')
Resultados de validación cruzada (LOOCV) para kriging
cv_summary %>%
kable(align = "rrr") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
|
RMSE
|
MAE
|
ME
|
|
1.070817
|
0.8444086
|
-0.0058144
|
Conclusiones
Este análisis demostró la utilidad de las herramientas
geoestadísticas para modelar y predecir la variabilidad espacial de la
temperatura en plantaciones de aguacate Hass, utilizando datos primarios
recolectados en la Finca Guadalupe Hass de El Tambo, Cauca. La
metodología aplicada, desde la exploración de datos, el ajuste y
selección de modelos de variograma, hasta la interpolación espacial
mediante kriging y su validación, permitió obtener resultados sólidos,
mostrando patrones espaciales coherentes y estimaciones precisas a
escala de lote.
Estos hallazgos adquieren especial relevancia en el contexto de El
Tambo, un municipio destacado en la producción de aguacate Hass gracias
a sus condiciones de altitud y clima favorables. Además, el desarrollo
sostenible y la transformación productiva en la región se fortalecen con
la participación de familias campesinas, indígenas y afrocolombianas,
así como la implementación de centros de acopio y buenas prácticas
agrícolas. El estudio evidencia el valor de integrar datos espaciales y
metodologías avanzadas para apoyar la toma de decisiones en territorios
rurales en procesos de desarrollo y transición.