Planteamiento del Problema

A partir de la base de datos “Datos_Completos_Aguacate.xlsx” que contiene información sobre las variables climatológicas y de terreno de una finca en el departamento de Cauca (Colombia), tomando como filtro únicamente el periodo “01/10/2020 10:11:12 a, m,” y usando la variable “Temperature”, se debe realizar el análisis geoestadístico, siguiendo los pasos:

  • Evaluar autocorrelación espacial con el semivariograma.
  • Identificar el mejor modelo teórico.
  • Realizar una predicción espacial usando la metodología krigin.
  • Generar imagen de la predicción espacial.

Si en algún evento la variable “Temperature” no tiene una autocorrelación espacial siginificativa, se puede seleccionar otra variable para realizar el desarrollo de la actividad (pueden ser “Relative_Humidity”, “Wind_Speed”, “Altitude”).

Desarrollo de la actividad

Análisis Exploratorio y Limpieza de datos

Antes de desarrollar los puntos, realizamos un análisis exploratorio para limpiar la base de datos de datos faltantes y posibles inconsistencias, observemos que tipo de variables disponemos.

# Importar base de datos solicitada
FincaAguacate_Excel <- "C:/Users/Christian/Desktop/Carpeta del Todo/Cursos Maestria en Ciencia de Datos/07 - Analisis de datos geograficos y espaciales/Unidad 2.1 - Exploracion de datos con Geoestadistica/Datos_Completos_Aguacate.xlsx"
FincaAguacate= suppressMessages(suppressWarnings(read_excel(FincaAguacate_Excel)))

#Base de datos solicitada para este trabajo
str(FincaAguacate, vec.len = 2, give.attr = FALSE)
## tibble [20,271 × 21] (S3: tbl_df/tbl/data.frame)
##  $ id_arbol                      : chr [1:20271] "1" "2" ...
##  $ Latitude                      : num [1:20271] 2.38 2.38 ...
##  $ Longitude                     : num [1:20271] -76.6 -76.6 ...
##  $ FORMATTED_DATE_TIME           : chr [1:20271] "21/08/2019  9:22:57 a, m," "21/08/2019  9:27:13 a, m," ...
##  $ Psychro_Wet_Bulb_Temperature  : num [1:20271] 14.8 11.6 12.9 14.1 14.3 ...
##  $ Station_Pressure              : num [1:20271] 805 805 ...
##  $ Relative_Humidity             : num [1:20271] 33.6 36.8 31.5 33.2 34.3 ...
##  $ Crosswind                     : num [1:20271] 0.2 3.6 0.4 0.6 0.4 ...
##  $ Temperature                   : num [1:20271] 25.7 20.8 23.7 25 25 ...
##  $ Barometric_Pressure           : num [1:20271] 805 805 ...
##  $ Headwind                      : num [1:20271] 0.7 3.5 0.7 0.7 0.4 ...
##  $ Direction_True                : num [1:20271] 166 314 332 139 129 ...
##  $ Direction_Mag                 : num [1:20271] 165 313 331 139 128 ...
##  $ Wind_Speed                    : num [1:20271] 0.8 5.1 0.8 0.9 0.6 ...
##  $ Heat_Stress_Index             : num [1:20271] 24.1 19.5 22 23.2 23.3 ...
##  $ Altitude                      : num [1:20271] 1896 1895 ...
##  $ Dew_Point                     : num [1:20271] 8.6 5.5 5.8 7.7 8.1 ...
##  $ Density_Altitude              : num [1:20271] 2.74 2.57 ...
##  $ Wind_Chill                    : num [1:20271] 25.7 20.8 23.7 24.9 24.9 ...
##  $ Estado_Fenologico_Predominante: num [1:20271] 715 715 715 715 715 ...
##  $ Frutos_Afectados              : num [1:20271] 0 3 0 0 1 ...

Iniciamos con una revisión de los datos faltantes. Dado que para esta actividad solo nos interesa los datos de ubicación (“Latitude” y “Longitude”), la fecha (“FORMATTED_DATE_TIME”) para poder realizar el filtro, y temperatura “Temperature”, solo se realizará el análisis para estas variables.

#Calculando datos faltantes
Datos_faltantes <- data.frame(colnames(FincaAguacate), sapply(FincaAguacate, function(x) sum(is.na(x))))
Datos_faltantes <- Datos_faltantes[c(2:4, 9), ]

#Limpiando Dataframe
rownames(Datos_faltantes) <- NULL
colnames(Datos_faltantes) <- c("Variable", "Datos Faltantes")

#Presentando información en formato tabla
kable_classic(kbl(Datos_faltantes, caption = "<center><b>Tabla 1. Datos Faltantes por Variable</b></center>"), full_width = F)
Tabla 1. Datos Faltantes por Variable
Variable Datos Faltantes
Latitude 0
Longitude 0
FORMATTED_DATE_TIME 0
Temperature 0

Vemos que ninguna de las variables evaluadas presenta datos faltantes.

Preparación de los datos

Primero filtramos la base de datos por el periodo solicitado que es “01/10/2020 10:11:12 a, m,”.
# Filtramos la cadena de texto solicitada
FincaAguacate_Filtro <- FincaAguacate[FincaAguacate$FORMATTED_DATE_TIME == "01/10/2020 10:11:12 a, m,",]
print(FincaAguacate_Filtro)
## # A tibble: 0 × 21
## # ℹ 21 variables: id_arbol <chr>, Latitude <dbl>, Longitude <dbl>,
## #   FORMATTED_DATE_TIME <chr>, Psychro_Wet_Bulb_Temperature <dbl>,
## #   Station_Pressure <dbl>, Relative_Humidity <dbl>, Crosswind <dbl>,
## #   Temperature <dbl>, Barometric_Pressure <dbl>, Headwind <dbl>,
## #   Direction_True <dbl>, Direction_Mag <dbl>, Wind_Speed <dbl>,
## #   Heat_Stress_Index <dbl>, Altitude <dbl>, Dew_Point <dbl>,
## #   Density_Altitude <dbl>, Wind_Chill <dbl>, …
Nos encontramos con la sorpresa de que no ha resultado ningún dato del filtro, acá buscamos un registro que contenga el dato y realizar una verificación.
# Encontramos registros que contengan el dato
print(head(FincaAguacate[grepl(
  "01/10/2020",FincaAguacate$FORMATTED_DATE_TIME), ][c(1:4)], 5))
## # A tibble: 5 × 4
##   id_arbol Latitude Longitude FORMATTED_DATE_TIME       
##   <chr>       <dbl>     <dbl> <chr>                     
## 1 1            2.39     -76.7 01/10/2020  10:11:12 a, m,
## 2 2            2.39     -76.7 01/10/2020  10:11:12 a, m,
## 3 3            2.39     -76.7 01/10/2020  10:11:12 a, m,
## 4 4            2.39     -76.7 01/10/2020  10:11:12 a, m,
## 5 5            2.39     -76.7 01/10/2020  10:11:12 a, m,
Encontramos que el registro 9140 contiene el registro, podría quedarme usando un filtro de “contiene” (y correr el riesgo de incluir datos que quizás no deberían estar), pero se hará una revisión más allá para verificar y corregir el posible error de la base de datos, revisamos las cadenas de texto para ver qué ocurre, si hay alguna diferencia entre el dato “digitado” y el registro.
# Verificamos los valores hexadecimales de ambas cadenas de texto
charToRaw(FincaAguacate$FORMATTED_DATE_TIME[9140])
##  [1] 30 31 2f 31 30 2f 32 30 32 30 c2 a0 20 31 30 3a 31 31 3a 31 32 20 61 2c 20
## [26] 6d 2c
charToRaw("01/10/2020  10:11:12 a, m,")
##  [1] 30 31 2f 31 30 2f 32 30 32 30 20 20 31 30 3a 31 31 3a 31 32 20 61 2c 20 6d
## [26] 2c
Vemos que la diferencia respecto del valor digitado es “c2 a0”, investigando este valor se encuentra que este corresponde a un caracter denominado “Non-breaking space”, en español denominado “Espacio duro” o “Espacio irrompible” que se usa para evitar que una línea genere un salto, lo cierto es que este es un caracter normalmente invisible, por eso no se podía filtrar adecuadamente, se procede entonces a eliminar la fuente del problema.
# Eliminar espacios no quiebre
FincaAguacate_fix <- FincaAguacate
FincaAguacate_fix$FORMATTED_DATE_TIME <- gsub(
  "\u00A0", " ", FincaAguacate_fix$FORMATTED_DATE_TIME)

# Filtramos nuevamente la cadena de texto solicitada
FincaAguacate_Filtro <- FincaAguacate_fix[
  FincaAguacate_fix$FORMATTED_DATE_TIME == "01/10/2020  10:11:12 a, m,",]
print(FincaAguacate_Filtro)
## # A tibble: 534 × 21
##    id_arbol Latitude Longitude FORMATTED_DATE_TIME        Psychro_Wet_Bulb_Tem…¹
##    <chr>       <dbl>     <dbl> <chr>                                       <dbl>
##  1 1            2.39     -76.7 01/10/2020  10:11:12 a, m,                   22  
##  2 2            2.39     -76.7 01/10/2020  10:11:12 a, m,                   21.4
##  3 3            2.39     -76.7 01/10/2020  10:11:12 a, m,                   21.8
##  4 4            2.39     -76.7 01/10/2020  10:11:12 a, m,                   22.8
##  5 5            2.39     -76.7 01/10/2020  10:11:12 a, m,                   22.6
##  6 6            2.39     -76.7 01/10/2020  10:11:12 a, m,                   21.5
##  7 7            2.39     -76.7 01/10/2020  10:11:12 a, m,                   22.2
##  8 8            2.39     -76.7 01/10/2020  10:11:12 a, m,                   22.6
##  9 9            2.39     -76.7 01/10/2020  10:11:12 a, m,                   23  
## 10 10           2.39     -76.7 01/10/2020  10:11:12 a, m,                   22.7
## # ℹ 524 more rows
## # ℹ abbreviated name: ¹​Psychro_Wet_Bulb_Temperature
## # ℹ 16 more variables: Station_Pressure <dbl>, Relative_Humidity <dbl>,
## #   Crosswind <dbl>, Temperature <dbl>, Barometric_Pressure <dbl>,
## #   Headwind <dbl>, Direction_True <dbl>, Direction_Mag <dbl>,
## #   Wind_Speed <dbl>, Heat_Stress_Index <dbl>, Altitude <dbl>, Dew_Point <dbl>,
## #   Density_Altitude <dbl>, Wind_Chill <dbl>, …
Con esto hemos filtrado correctamente el dataframe y procedemos a convertirlo en objeto tipo geodata.
# Convertir dataframe en geodata
FincaAguacate_geo <- as.geodata(
  FincaAguacate_Filtro,coords.col = 3:2,data.col = 9)

# Gráficar geodata
par(mfrow = c(2, 1), mar = c(0, 4, 0, 4))
plot.new()
text(x = 0.5, y = 0.5, labels = "Gráfico 1. Objeto geodata de la\nvariable Temperatura", 
     cex = 1.7)
plot(FincaAguacate_geo)

Con ello se termina la preparación de los datos y continuamos con el primer punto, que corresponde a la elaboración del semivariograma.

1. Evaluar Semivariograma

Antes de elaborar el semivariograma debemos determinar hasta que distancia se debería graficar, normalmente lo recomendado es hasta el tercer cuartil de las distancias entre los puntos a evaluar, así que calculamos las distancias y verificamos el dato.
# Calculamos las estadísticas de los puntos de estudio
summary(dist(FincaAguacate_Filtro[3:2]))
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 1.712e-05 4.051e-04 6.408e-04 6.827e-04 9.178e-04 1.959e-03
Tomamos el dato del tercer cuartil, y se sube algo más arriba y elaboramos el semivariograma.
# Crear variograma
FincaAguacate_variog <- variog(FincaAguacate_geo,option = "bin",
                               uvec=seq(0,9.178e-04,9.178e-05), messages = FALSE)

# Calcular margen de correlación
FincaAguacate_marks <- variog.mc.env(FincaAguacate_geo,
                                     obj=FincaAguacate_variog, messages = FALSE)

# Graficar semivariograma
plot(FincaAguacate_variog, main = "Gráfico 2. Semivariograma de Temperatura",
     xlab = "Distancia", ylab = "Semivarianza")
lines(FincaAguacate_marks)

Con la gráfica del semivariograma podemos observar que temperatura tiene una correlación espacial que se podría considerar sobre lo mínimo aceptable, entonces se decide probar con otras variables. Empecemos con humedad relativa.
# Humedad relativa
# Convertir dataframe en geodata
FincaAguacate_geo2 <- as.geodata(
  FincaAguacate_Filtro,coords.col = 3:2,data.col = 7)

# Crear variograma
FincaAguacate_variog2 <- variog(FincaAguacate_geo2,option = "bin",
                                uvec=seq(0,9.178e-04,9.178e-05), messages = FALSE)

# Calcular margen de correlación
FincaAguacate_marks2 <- variog.mc.env(FincaAguacate_geo2,
                                      obj=FincaAguacate_variog2, messages = FALSE)

# Graficar semivariograma
plot(FincaAguacate_variog2, main = "Gráfico 3. Semivariograma de Humedad Relativa",
     xlab = "Distancia", ylab = "Semivarianza")
lines(FincaAguacate_marks2)

Realmente es complicado decir que humedad relativa tiene un comportamiento diferente a temperatura, la gráfica pareciera mejorar hacia el final pero al igual que temperatura, tiene 3 puntos dentro de la zona de no correlación y su gráfica no es substancialmente diferente de la de temperatura, se evalúa a continuación la velocidad del viento.
# Velocidad del viento
# Convertir dataframe en geodata
FincaAguacate_geo2 <- as.geodata(
  FincaAguacate_Filtro,coords.col = 3:2,data.col = 14)

# Crear variograma
FincaAguacate_variog2 <- variog(FincaAguacate_geo2,option = "bin",
                                uvec=seq(0,9.178e-04,9.178e-05), messages = FALSE)

# Calcular margen de correlación
FincaAguacate_marks2 <- variog.mc.env(FincaAguacate_geo2, 
                                      obj=FincaAguacate_variog2, messages = FALSE)

# Graficar semivariograma
plot(FincaAguacate_variog2, main = "Gráfico 4. Semivariograma de Velocidad del Viento",
     xlab = "Distancia", ylab = "Semivarianza")
lines(FincaAguacate_marks2)

Con velocidad del viento es evidente que la variable no tiene una correlación espacial, finalmente se revisa la variable altitud.
# Altitud
# Convertir dataframe en geodata
FincaAguacate_geo2 <- as.geodata(
  FincaAguacate_Filtro,coords.col = 3:2,data.col = 16)

# Crear variograma
FincaAguacate_variog2 <- variog(FincaAguacate_geo2,option = "bin",
                                uvec=seq(0,9.178e-04,9.178e-05), messages = FALSE)

# Calcular margen de correlación
FincaAguacate_marks2 <- variog.mc.env(FincaAguacate_geo2,
                                      obj=FincaAguacate_variog2, messages = FALSE)

# Graficar semivariograma
plot(FincaAguacate_variog2, main = "Gráfico 5. Semivariograma de Altitud",
     xlab = "Distancia", ylab = "Semivarianza")
lines(FincaAguacate_marks2)

Altitud pareciera tener un comportamiento incluso lineal, no parece estabilizarse en el rango evaluado.
Dado que ninguna variable tiene un comportamiento fuerte de correlación espacial, se continuará la actividad con la variable original, temperatura.

2. Identificar Modelo Teórico

Escogiendo la variable de temperatura, procedemos a graficar los modelos para visualizar su grado de ajuste con los datos.
#Fijar rango de evaluación
val_ini <- expand.grid(seq(1.5,3,l=10), seq(4e-04,6e-04,l=10))

# Gráficar semiovariograma junto a las curvas teóricas
plot(FincaAguacate_variog, main = "Gráfico 6. Semivariograma de Temperatura\ncon modelos teóricos",
     xlab = "Distancia", ylab = "Semivarianza")
FincaAguacate_exp <- variofit(FincaAguacate_variog, ini=val_ini,
                                 cov.model="exponential", wei="npair",
                                 min="optim", messages = FALSE)
FincaAguacate_gaus <- variofit(FincaAguacate_variog, ini=val_ini,
                               cov.model="gaussian", wei="npair",
                               min="optim",nugget = 0, messages = FALSE)
FincaAguacate_spe <- variofit(FincaAguacate_variog, ini=val_ini, 
                              cov.model="spheric",fix.nug=TRUE, 
                              wei="npair", min="optim", messages = FALSE)
lines(FincaAguacate_exp,col="blue")
lines(FincaAguacate_gaus,col="red")
lines(FincaAguacate_spe,col="yellow")

Gráficamente parece que el modelo exponencial se ajusta mejor a los datos, pero revisemos que nos dice la suma de errores al cuadrado para tener un indicador numérico de ajuste.
#Crear dataframe de la summa de errores cuadrados por modelo
Errores_cuadrado <- data.frame(Modelo=c("Exponencial", "Gaussiano", "Esférico"),
                           Suma_Errores=c(FincaAguacate_exp$value, FincaAguacate_gaus$value, FincaAguacate_spe$value))

#Crear tabla para visualizar la suma de errores cuadrados
kbl(Errores_cuadrado, caption = "<center><b>Tabla 2. Suma de Errores al cuadrado por Modelo</b></center>", col.names=c("Modelo","Suma de errores al cuadrado"))%>%
  kable_classic(full_width = F)
Tabla 2. Suma de Errores al cuadrado por Modelo
Modelo Suma de errores al cuadrado
Exponencial 4857.673
Gaussiano 14947.769
Esférico 6583.649
Vemos que el modelo exponencial tuvo un mejor indicador, seguido no tan lejos del esférico, el modelo gaussiano no funcionó bien para esta variable, de entrada no graficó muy bien, viéndose más como dos rectas unidas que como una función de curva, quizás se deba a la baja correlación espacial del modelo.

3. Realizar Predicción Espacial

Para realizar la predicción espacial, primero se necesita obtener el área donde va a ser graficada la predicción, para ello obtenemos el contorno brindado por los puntos extremos de latitud y longitud en la base de datos.
#Crear dataframe del área a gráficar
area_val <- data.frame(Modelo=c("Min. Long", "Max Long.", "Min. Lat", "Max. Lat"),
                               Suma_Errores=c(min(FincaAguacate_Filtro[3]), max(FincaAguacate_Filtro[3]), min(FincaAguacate_Filtro[2]), max(FincaAguacate_Filtro[2])))

#Crear tabla para visualizar los valores del área
kbl(area_val, caption = "<center><b>Tabla 3. Rango de área a graficar</b></center>", col.names=c("Línea","Valor"))%>%
  kable_classic(full_width = F)
Tabla 3. Rango de área a graficar
Línea Valor
Min. Long -76.711799
Max Long. -76.710215
Min. Lat 2.392101
Max. Lat 2.393634
A modo de visualización, se gráfica como queda la “grilla”, donde se realizará la predicción espacial.
# Graficar grilla de terreno
FincaAguacate_grilla <- expand.grid(lon=seq(-76.7118, -76.71022, l=100),
                                 lat=seq(2.392101, 2.393634, l=100))
plot(FincaAguacate_grilla, main = "Gráfico 7. Grilla del terreno",
     xlab = "Longitud", ylab = "Latitud")
points(FincaAguacate_Filtro[3:2],col="yellow")

Ya teniendo una visualización del terreno, se procede a realizar la predicción espacial de la temperatura del terreno.
# Crear predicción, pasando modelo
salida <- output.control(messages=FALSE)
FincaAguacate_pred <- krige.conv(
  FincaAguacate_geo, loc=FincaAguacate_grilla, output = salida,
  krige= krige.control(obj.model = FincaAguacate_exp))

# Gráficar predicción
par(mfrow=c(1,2))
image(FincaAguacate_pred, main="Gráfico 8. Predicción Espacial",
      xlab="Longitud", ylab="Latitud")
par(new=TRUE)
contour(FincaAguacate_pred, xlab="Longitud", ylab="Latitud", drawlabels=TRUE)

También podemos generar, si así se desea, una visualización gráfica espacial delerror de los datos.
# Gráficar desviación del error predicción
par(mfrow=c(1,2))
image(FincaAguacate_pred, main="Gráfico 9. Error de la Predicción\nEspacial", 
      val=sqrt(FincaAguacate_pred$krige.var), xlab="Longitud", ylab="Latitud")
par(new=TRUE)
contour(FincaAguacate_pred, xlab="Longitud", 
        val=sqrt(FincaAguacate_pred$krige.var), ylab="Latitud", drawlabels=TRUE)

4. Generar Raster

Ahora también podemos crear imágenes raster a partir de las predicciones realizadas.
# Creando mapa raster a partir de los datos
FincaAguacate_tempPred <- rasterFromXYZ(cbind(FincaAguacate_grilla, FincaAguacate_pred$predict))
plot(FincaAguacate_tempPred, main="Gráfico 10. Mapa raster de temperatura",
     xlab="Longitud", ylab="Latitud")

Ahora también podemos crear imágenes raster a partir de las predicciones realizadas.
# Creando mapa raster del error a partir de los datos
FincaAguacate_errorPred <- rasterFromXYZ(cbind(FincaAguacate_grilla, val=sqrt(FincaAguacate_pred$krige.var)))
plot(FincaAguacate_errorPred, main="Gráfico 11. Mapa raster del error de la predicción",
     xlab="Longitud", ylab="Latitud")

Para cerrar se realiza una validación del modelo exponencial, realizamos una validación cruzada.
FincaAguacate_valid=xvalid(geodata = FincaAguacate_geo, 
                           model = FincaAguacate_exp)
## xvalid: number of data locations       = 534
## xvalid: number of validation locations = 534
## xvalid: performing cross-validation at location ... 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 
## xvalid: end of cross-validation
Se calcula el error absoluto medio para dar un indicador general del error del modelo.
MAE=mean(abs(FincaAguacate_valid$error))
print(MAE)
## [1] 0.7909316
El modelo presenta un error de predicción de acuerdo con la validación cruzada de 0.79 grados, lo cual no parece demasiado significativo en la predicción, se puede decir solo considerando este indicador que el modelo tuvo un buen ajuste.

5. Conclusiones

A partir de los resultados obtenidos podemos señalar las siguientes conclusiones y observaciones:
  • De acuerdo a los mostrado en el objeto geodata, la temperatura no presenta un patrón estacionario, es decir, la temperatura de la zona no se distribuye en forma de gradiente uniforme.
  • La correlación de temperatura encontrada no es muy fuerte, lo que implica que puede haber otros factores subyacentes que afectan la temperatura de la zona o que la temperatura no es afectada de manera importante por la distribución del terreno. Esto puede generar que los modelos de predicción pierdan capacidad de predecir adecuadamente los valores de temperatura en la zona.
  • El modelo que presentó el mejor ajuste fue el modelo exponencial, al final en la validación cruzada su error absoluto medio en la temperatura con respecto del valor encontrado en cada punto evaluado fue de 0.79 grados, lo cual no es demasiado significativo, y para los parámetros dados puede decirse que el modelo tuvo un buen grado de ajuste.