Geoestadística univariada con geoR

Geoestadística univariada con geoR

Parte descriptiva

Librerías

Lista de librerías con link a la documentación.

rm(list=ls())
library(fields)
Cargando paquete requerido: spam
Spam version 2.11-0 (2024-10-03) is loaded.
Type 'help( Spam)' or 'demo( spam)' for a short introduction 
and overview of this package.
Help for individual functions is also obtained by adding the
suffix '.spam' to the function name, e.g. 'help( chol.spam)'.

Adjuntando el paquete: 'spam'
The following objects are masked from 'package:base':

    backsolve, forwardsolve
Cargando paquete requerido: viridisLite

Try help(fields) to get started.
library(geoR)
--------------------------------------------------------------
 Analysis of Geostatistical Data
 For an Introduction to geoR go to http://www.leg.ufpr.br/geoR
 geoR version 1.9-4 (built on 2024-02-14) is now loaded
--------------------------------------------------------------
library(akima)

Lectura de datos

aquifer <- read.table("data/aquifer.txt", head = TRUE, dec = ",")

Encabezado de datos aquifer.txt

head(aquifer)
       Este     Norte Profundidad
1  42.78275 127.62282        1464
2 -27.39691  90.78732        2553
3  -1.16289  84.89600        2158
4 -18.61823  76.45199        2455
5  96.46549  64.58058        1756
6 108.56243  82.92325        1702

Summary de los datos aquifer.txt

summary(aquifer)
      Este             Norte          Profundidad  
 Min.   :-145.24   Min.   :  9.414   Min.   :1024  
 1st Qu.: -21.30   1st Qu.: 33.682   1st Qu.:1548  
 Median :  11.66   Median : 59.158   Median :1797  
 Mean   :  16.89   Mean   : 79.361   Mean   :2002  
 3rd Qu.:  70.90   3rd Qu.:131.825   3rd Qu.:2540  
 Max.   : 112.80   Max.   :184.766   Max.   :3571  

GEO_Data

Convertir aquifer a un objeto geodata (geoR obj)

aquiferg <- as.geodata(aquifer)
summary(aquiferg)
Number of data points: 85 

Coordinates summary
         Este     Norte
min -145.2365   9.41441
max  112.8045 184.76636

Distance summary
        min         max 
  0.2211656 271.0615463 

Data summary
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
1024.000 1548.000 1797.000 2002.282 2540.000 3571.000 

Gráfico de objeto geodata

Gráfico del objeto geodata

plot(aquiferg, qt.col = c("purple",
                         "pink",
                         "green",
                         "yellow"))

Gráfico con el parametro 3d

plot(aquiferg, scatter3d = T)

Gráfico removiendo la tendencia (trend )

plot(aquiferg, trend = "1st")

Gráficos descriptivos interpolación

par(mfrow = c(2, 2),
    mar = c(3, 3, 1, 1),
    mgp = c(2, 1, 0))
# Esta función agrupa los siguientes gráficos en
# una matrix 2x2

grillas <- interp(aquifer$Este,
                  aquifer$Norte,
                  aquifer$Profundidad)

persp(grillas$x,
      grillas$y,
      grillas$z,
      xlab = "Este",
      ylab = "Norte",
      zlab = "Nivel freatico",
      phi = 30,
      theta = 20,
      col = "lightblue",
      expand = .5,
      ticktype = "detailed")

drape.plot(grillas$x,
           grillas$y,
           grillas$z,
           xlab = "Este",
           ylab = "Norte",
           zlab = "z",
           theta = 45,
           col = topo.colors(64),
           expand = .5,
           ticktype = "detailed")


drape.plot(grillas$x,
           grillas$y,
           grillas$z,
           xlab = "Este",
           ylab = "Norte",
           zlab = "z",
           theta = -10,
           col = topo.colors(64),
           expand = .5,
           ticktype = "detailed")


drape.plot(grillas$x,
           grillas$y,
           grillas$z,
           xlab = "Este",
           ylab = "Norte",
           zlab = "z",
           theta = 60,
           col = topo.colors(64),
           expand = .5,
           ticktype = "detailed")

Gráficos de contorno

par(mfrow = c(2, 1),
    mar = c(1,1,1,1))

contour(grillas, nlevels = 10, main = "Contorno")
image(grillas$z, main =  "Grilla")

filled.contour(grillas, levels = seq(1000,
                                     5000,
                                     len = 10),
               col = heat.colors(10),
                main = "grilla niveles")

Funciones y gráficas a partir de la función outer

h <- seq(0, 1, len = 50)
u <- seq(0, 1, len = 50)

ejemplo1CH  <- function(h, u, sigma, a, b, c, d, delta) {
    (sigma^2/((a^2*u^2+c)^(d/2)))*exp(-(b^2*h^2)/(a^2*u^2+c))*exp(-delta*u^2)
    }
h <- seq(0, 1, len = 20)
u <- seq(1, 10, len = 20)
f <- outer(h, u, ejemplo1CH, sigma=3, a=1, b=3, c=1, d=2, delta=0)

par(mfrow = c(2, 2),
    mar = c(3, 3, 1, 1),
    mgp = c(2, 1, 0))

drape.plot(h,
           u,
           f,
           main = "Cressie-Huang; 1 (25,1,0.6)",
           xlab = "h",
           ylab = "u",
           zlab = "Covarianza",
           ltheta = 75,
           col = terrain.colors(64))

drape.plot(h,
           u,
           f,
           main = "Cressie-Huang; 1 (25,1,0.6)",
           xlab = "h",
           ylab = "u",
           zlab = "Covarianza",
           theta = -150,
           col = terrain.colors(64))
persp(h,
      u,
      f,
      main = "Cressie-Huang; 1 (25,1,0.6)",
      xlab = "h",
      ylab = "u",
      zlab = "Covarianza",
      ltheta = 75)

contour(h,
        u,
        f,
        col = topo.colors(10),
        xlim = c(0,0.6))

Modelando la media con regresión polinomial

Primer modelo

reg1 <- lm(Profundidad ~ Este + Norte, data = aquifer)
residuales1  <-  residuals(reg1)
summary(reg1)

Call:
lm(formula = Profundidad ~ Este + Norte, data = aquifer)

Residuals:
    Min      1Q  Median      3Q     Max 
-366.96 -161.53  -30.71  148.15  651.20 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 2591.4302    38.9599   66.52   <2e-16 ***
Este          -6.7514     0.3438  -19.64   <2e-16 ***
Norte         -5.9872     0.4066  -14.73   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 203.3 on 82 degrees of freedom
Multiple R-squared:  0.8921,    Adjusted R-squared:  0.8894 
F-statistic: 338.9 on 2 and 82 DF,  p-value: < 2.2e-16
anova(reg1)
Analysis of Variance Table

Response: Profundidad
          Df   Sum Sq  Mean Sq F value    Pr(>F)    
Este       1 19045642 19045642  460.95 < 2.2e-16 ***
Norte      1  8960172  8960172  216.86 < 2.2e-16 ***
Residuals 82  3388069    41318                      
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Segundo modelo

reg2 <- lm(Profundidad ~ Este + Norte +
           I(Este^2) + I(Norte^2) +
           I(Este * Norte),
           data = aquifer)
residuales2  <-  residuals(reg2)
summary(reg2)

Call:
lm(formula = Profundidad ~ Este + Norte + I(Este^2) + I(Norte^2) + 
    I(Este * Norte), data = aquifer)

Residuals:
    Min      1Q  Median      3Q     Max 
-407.43 -138.76   -5.74  128.84  648.16 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)      2.481e+03  6.813e+01  36.424  < 2e-16 ***
Este            -8.374e+00  5.525e-01 -15.157  < 2e-16 ***
Norte           -2.043e+00  1.764e+00  -1.159 0.250146    
I(Este^2)        1.417e-03  4.987e-03   0.284 0.777096    
I(Norte^2)      -2.464e-02  9.298e-03  -2.650 0.009708 ** 
I(Este * Norte)  2.680e-02  7.413e-03   3.616 0.000526 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 185.9 on 79 degrees of freedom
Multiple R-squared:  0.9131,    Adjusted R-squared:  0.9076 
F-statistic:   166 on 5 and 79 DF,  p-value: < 2.2e-16
anova(reg2)
Analysis of Variance Table

Response: Profundidad
                Df   Sum Sq  Mean Sq  F value    Pr(>F)    
Este             1 19045642 19045642 551.3469 < 2.2e-16 ***
Norte            1  8960172  8960172 259.3855 < 2.2e-16 ***
I(Este^2)        1    55368    55368   1.6028 0.2092235    
I(Norte^2)       1   152170   152170   4.4051 0.0390253 *  
I(Este * Norte)  1   451567   451567  13.0723 0.0005259 ***
Residuals       79  2728964    34544                       
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Tercer modelo

reg3 <- lm(Profundidad ~ Este * Norte,
           data = aquifer)
residuales3  <-  residuals(reg3)
summary(reg3)

Call:
lm(formula = Profundidad ~ Este * Norte, data = aquifer)

Residuals:
    Min      1Q  Median      3Q     Max 
-406.30 -138.88  -13.04  129.36  722.48 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  2.627e+03  3.833e+01  68.546  < 2e-16 ***
Este        -8.287e+00  5.658e-01 -14.646  < 2e-16 ***
Norte       -6.649e+00  4.327e-01 -15.366  < 2e-16 ***
Este:Norte   2.452e-02  7.401e-03   3.314  0.00138 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 191.9 on 81 degrees of freedom
Multiple R-squared:  0.905, Adjusted R-squared:  0.9014 
F-statistic: 257.1 on 3 and 81 DF,  p-value: < 2.2e-16
anova(reg3)
Analysis of Variance Table

Response: Profundidad
           Df   Sum Sq  Mean Sq F value    Pr(>F)    
Este        1 19045642 19045642  517.06 < 2.2e-16 ***
Norte       1  8960172  8960172  243.25 < 2.2e-16 ***
Este:Norte  1   404448   404448   10.98  0.001379 ** 
Residuals  81  2983621    36835                      
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Estimación del semivariograma empírico

vari2 <- variog(aquiferg, trend = "1st")
variog: computing omnidirectional variogram
vari2Cloud <- variog(aquiferg, op = "cloud", trend = "1st")
variog: computing omnidirectional variogram
vari2BinCloud <- variog(aquiferg,
                       max.dist = 200,
                       op = "cloud",
                       bin.cloud = TRUE)
variog: computing omnidirectional variogram
vari2Sm <- variog(aquiferg,
                  trend = "1st",
                  op = "sm",
                  band=11)
variog: computing omnidirectional variogram
par(mfrow = c(2, 2), mar = c(3, 3, 1, 1), mgp = c(2, 1, 0))
     plot(vari2$u, vari2$v, main = "binned variogram") 
     plot(vari2Cloud$u, vari2Cloud$v, main = "variogram cloud")
     plot(vari2BinCloud$u, vari2BinCloud$v, main = "clouds for binned variogram")
     plot(vari2Sm$u, vari2Sm$v, main = "smoothed variogram")

Explorando estimación clásica, removiendo tendencia

vari1 <- variog(aquiferg)
variog: computing omnidirectional variogram
vari2 <- variog(aquiferg, trend = "1st")
variog: computing omnidirectional variogram
vari3 <- variog(aquiferg, trend = "2nd")
variog: computing omnidirectional variogram
plot(vari1$u,vari1$v, main = "Sin remover tendencia")

plot(vari2$u,vari2$v, main  = "Trend 1 ")

plot(vari3$u,vari3$v, main  = "Trend 2 ")

Explorando estimación resistente a datos atípicos y removiendo tendencia

vari1 <- variog(aquiferg, estimator.type = "modulus")
variog: computing omnidirectional variogram
vari2 <- variog(aquiferg, trend = "1st", estimator.type = "modulus")
variog: computing omnidirectional variogram
vari3 <- variog(aquiferg, trend = "2nd", estimator.type = "modulus")
variog: computing omnidirectional variogram
plot(vari1$u,vari1$v, main = "Sin remover tendencia")

plot(vari2$u,vari2$v, main  = "Trend 1 ")

plot(vari3$u,vari3$v, main  = "Trend 2 ")

Explorando anisotropía

vari_0 <- variog(aquiferg,
                 trend = "1st",
                 max.dist = 200,
                 dir = 0)
variog: computing variogram for direction = 0 degrees (0 radians)
        tolerance angle = 22.5 degrees (0.393 radians)
vari_45 <- variog(aquiferg,
                  trend = "1st",
                  max.dist = 200,
                  dir = pi / 4)
variog: computing variogram for direction = 45 degrees (0.785 radians)
        tolerance angle = 22.5 degrees (0.393 radians)
vari_90 <- variog(aquiferg,
                  trend = "1st",
                  max.dist = 200,
                  dir = pi / 2)
variog: computing variogram for direction = 90 degrees (1.571 radians)
        tolerance angle = 22.5 degrees (0.393 radians)
vari_135 <- variog(aquiferg,
                   trend = "1st",
                   max.dist = 200,
                   dir = 3 * pi / 4)
variog: computing variogram for direction = 135 degrees (2.356 radians)
        tolerance angle = 22.5 degrees (0.393 radians)
par(mfrow = c(2, 2),
    mar = c(3, 3, 1, 1),
    mgp = c(2, 1, 0))

plot(vari_0$u,vari_0$v, main = "vari 0")
plot(vari_45$u,vari_45$v, main = "vari 45")
plot(vari_90$u,vari_90$v, main = "vari 90")
plot(vari_135$u,vari_135$v, main = "vari 195")

Estimación teórica del semivariograma

var1 <- variog(aquiferg,trend="1st",max.dist=200)
variog: computing omnidirectional variogram
#ini1 <- eyefit(var1)
#cov.model  sigmasq phi   tausq kappa kappa2   practicalRange
#1      wave 30805.52  13 8984.94  <NA>   <NA> 38.8889336320589
ini1 <- c(30805.52, 13)
fitvar1 <- variofit(var1,
                    cov.model = "wave",
                    ini1,
                    fix.nugget = TRUE,
                    nugget = 8984.94,
                    wei = "equal")
variofit: covariance model used is wave 
variofit: weights used: equal 
variofit: minimisation function used: optim 
fitvar2 <- variofit(var1,
                    cov.model = "wave",
                    ini1,
                    fix.nugget = TRUE,
                    nugget = 8984.94,
                    wei = "npairs")
variofit: covariance model used is wave 
variofit: weights used: npairs 
variofit: minimisation function used: optim 
fitvar3 <- variofit(var1,
                    ini1,
                    fix.nugget = TRUE,
                    nugget = 8984.94,
                    wei = "cressie")
variofit: covariance model used is matern 
variofit: weights used: cressie 
variofit: minimisation function used: optim 
fitvar4 <- likfit(aquiferg,
                  coords = aquiferg$coords,
                  data = aquiferg$data,
                  trend = "1st",
                  ini.cov.pars = ini1,
                  fix.nugget = T,
                  nugget = 8984.94,
                  cov.model = "wave",
                  lik.method = "ML")
kappa not used for the wave correlation function
---------------------------------------------------------------
likfit: likelihood maximisation using the function optim.
likfit: Use control() to pass additional
         arguments for the maximisation function.
        For further details see documentation for optim.
likfit: It is highly advisable to run this function several
        times with different initial values for the parameters.
likfit: WARNING: This step can be time demanding!
---------------------------------------------------------------
likfit: end of numerical maximisation.
fitvar5 <- likfit(aquiferg,
                  coords = aquiferg$coords,
                  data = aquiferg$data,
                  trend = "1st",
                  ini.cov.pars = ini1,
                  fix.nugget = T,
                  nugget = 8984.94,
                  cov.model = "wave",
                  lik.method = "REML")
kappa not used for the wave correlation function
---------------------------------------------------------------
likfit: likelihood maximisation using the function optim.
likfit: Use control() to pass additional
         arguments for the maximisation function.
        For further details see documentation for optim.
likfit: It is highly advisable to run this function several
        times with different initial values for the parameters.
likfit: WARNING: This step can be time demanding!
---------------------------------------------------------------
likfit: end of numerical maximisation.
plot(var1$u,var1$v,
     xlab = "h",
     ylab = "semivarianza",
     cex.lab = 1.3,
     cex.axis = 1.2,
     main = "Estimación teórica del modelo de semivariograma",
     col.main = 4, cex.main =1.3)
lines(fitvar1, col = 1)
lines(fitvar2, col = 2)
lines(fitvar3, col = 3)
lines(fitvar4, col = 4)
lines(fitvar5, col = 5)
legend(130, 18000,
       c("MCO", "MCPnpairs", "MCPcressie", "ML", "REML"),
       lwd = 2,
       lty = 2:7,
       col = 2:7,
       box.col = 9,
       text.col = 2:7)

Resultados

#summary(fitvar1)
#summary(fitvar2)
#summary(fitvar3)
#summary(fitvar4)
#summary(fitvar5)

Pulimiento de medianas

Esta es una alternativa al modelamiento de la media cuando los modelos de regresión polinómicos usuales no logran el objetivo de eliminar la tendencia ya sea porque el tipo de tendencia corresponde mas a unas ventanas móviles o porque hay presentes datos atípicos.

Cargar librerias

Lista de librerías con link a la documentación.

rm(list=ls())
library(gstat)
library(sp)
library(mvtnorm)

Adjuntando el paquete: 'mvtnorm'
The following objects are masked from 'package:spam':

    rmvnorm, rmvt

Grilla de las ubicaciones espaciales.

n_x <- 4
n_y <- 6
x <- seq(0, 1, len = n_x)
y <- seq(0, 1, len = n_y)
coordenadas <- as.data.frame(expand.grid(x, y))
names(coordenadas) <- c("X", "Y")

Encabezado coordenadas

X Y
0.0000000 0.0
0.3333333 0.0
0.6666667 0.0
1.0000000 0.0
0.0000000 0.2
0.3333333 0.2

Definición de objeto VGM

Esto define un objeto vgm que es el tipo de objeto que usa el paquete gstat para los modelos teóricos de variograma. Con este objeto se pueden definir modelos anidados.

vario <- vgm(10, # Punto de silla
             "Exp", # Modelo, ver documentación
             0.5)  # Rango
print(vario)
  model psill range
1   Exp    10   0.5

Matriz de varianza dadas coordenadas.

coordinates(coordenadas) <- ~X + Y
#class(coordenadas) # Cambio de objedto dataframe a sp
cov_mat <- vgmArea(coordenadas, # Matriz de ubiaciones SP
        vgm = vario) # VGM object

print(dim(cov_mat))
[1] 24 24

Simulación.

Simulación dada la media y la matriz de varianza

mu  <- rep(0, n_x * n_y) # Media del proceso
simu <- rmvnorm(1,
                mean = mu,
                sigma = cov_mat)
print(simu[1:5])
[1] -2.5276981 -3.3094359 -2.1348143 -2.1178287 -0.4909082

Pulimiento de medianas

Unir las coordenadas con la columna de simulación

data <- as.data.frame(cbind(coordenadas@coords,
                            Simula = t(simu)))
names(data) <- c("X", "Y", "Var")
print(head(data))
          X   Y        Var
1 0.0000000 0.0 -2.5276981
2 0.3333333 0.0 -3.3094359
3 0.6666667 0.0 -2.1348143
4 1.0000000 0.0 -2.1178287
5 0.0000000 0.2 -0.4909082
6 0.3333333 0.2  1.2719638

Reshape para matriz, esto transforma la tabla de datos en matriz

tabla <- reshape2::dcast(data,
                         X ~ Y,
                         value.var = "Var")
rownames(tabla) <- tabla[, 1]
tabla <- tabla[, c(-1)]
print(tabla)
                          0        0.2        0.4        0.6        0.8
0                 -2.527698 -0.4909082  0.1769342 -0.5741717 -3.2540635
0.333333333333333 -3.309436  1.2719638 -0.1281840 -2.0756205 -3.7658826
0.666666666666667 -2.134814 -1.7383521 -4.3067516 -2.2423719 -2.1071125
1                 -2.117829 -2.5652753  0.3519380  0.9776769  0.6624249
                           1
0                 -7.5598239
0.333333333333333 -4.3110200
0.666666666666667 -0.2338448
1                 -0.5619844

Pulimiento de medianas de la tabla

med <- medpolish(tabla)
1: 29.66129
Final: 29.66129
geo_data <- reshape2::melt(med$residuals)
print(med)

Median Polish Results (Dataset: "tabla")

Overall: -1.688942

Row Effects:
                0 0.333333333333333 0.666666666666667                 1 
        0.2337905        -0.9078028        -0.2337905         1.5049076 

Column Effects:
         0        0.2        0.4        0.6        0.8          1 
-0.8926191  0.5743117  1.0840288  0.7010518 -0.6767591 -1.0461128 

Residuals:
                         0      0.2      0.4      0.6      0.8        1
0                 -0.17993  0.38993  0.54806  0.17993 -1.12215 -5.05856
0.333333333333333  0.17993  3.29440  1.38453 -0.17993 -0.49238 -0.66816
0.666666666666667  0.68054 -0.38993 -3.46805 -1.02069  0.49238  2.73500
1                 -1.04118 -2.95555 -0.54806  0.46066  1.52322  0.66816

Reshape de los datos, con efecto de la fila y la columna

tabla_residuales <- as.data.frame(med$residuals)
names(tabla_residuales) <- med$col
rownames(tabla_residuales) <- med$row
geo_data <- reshape2::melt(as.matrix(tabla_residuales))

geo_data <- cbind(data,
                  geo_data,
                  med$overall)
names(geo_data) <- c("X",
                     "Y",
                     "Var",
                     "Efecto fila",
                     "Efecto columa",
                     "Residual",
                     "Efecto Global")
print(geo_data)
           X   Y        Var Efecto fila Efecto columa   Residual Efecto Global
1  0.0000000 0.0 -2.5276981   0.2337905    -0.8926191 -0.1799278     -1.688942
2  0.3333333 0.0 -3.3094359  -0.9078028    -0.8926191  0.1799278     -1.688942
3  0.6666667 0.0 -2.1348143  -0.2337905    -0.8926191  0.6805371     -1.688942
4  1.0000000 0.0 -2.1178287   1.5049076    -0.8926191 -1.0411754     -1.688942
5  0.0000000 0.2 -0.4909082   0.2337905     0.5743117  0.3899314     -1.688942
6  0.3333333 0.2  1.2719638  -0.9078028     0.5743117  3.2943967     -1.688942
7  0.6666667 0.2 -1.7383521  -0.2337905     0.5743117 -0.3899314     -1.688942
8  1.0000000 0.2 -2.5652753   1.5049076     0.5743117 -2.9555528     -1.688942
9  0.0000000 0.4  0.1769342   0.2337905     1.0840288  0.5480566     -1.688942
10 0.3333333 0.4 -0.1281840  -0.9078028     1.0840288  1.3845317     -1.688942
11 0.6666667 0.4 -4.3067516  -0.2337905     1.0840288 -3.4680481     -1.688942
12 1.0000000 0.4  0.3519380   1.5049076     1.0840288 -0.5480566     -1.688942
13 0.0000000 0.6 -0.5741717   0.2337905     0.7010518  0.1799278     -1.688942
14 0.3333333 0.6 -2.0756205  -0.9078028     0.7010518 -0.1799278     -1.688942
15 0.6666667 0.6 -2.2423719  -0.2337905     0.7010518 -1.0206914     -1.688942
16 1.0000000 0.6  0.9776769   1.5049076     0.7010518  0.4606593     -1.688942
17 0.0000000 0.8 -3.2540635   0.2337905    -0.6767591 -1.1221531     -1.688942
18 0.3333333 0.8 -3.7658826  -0.9078028    -0.6767591 -0.4923789     -1.688942
19 0.6666667 0.8 -2.1071125  -0.2337905    -0.6767591  0.4923789     -1.688942
20 1.0000000 0.8  0.6624249   1.5049076    -0.6767591  1.5232183     -1.688942
21 0.0000000 1.0 -7.5598239   0.2337905    -1.0461128 -5.0585599     -1.688942
22 0.3333333 1.0 -4.3110200  -0.9078028    -1.0461128 -0.6681627     -1.688942
23 0.6666667 1.0 -0.2338448  -0.2337905    -1.0461128  2.7350003     -1.688942
24 1.0000000 1.0 -0.5619844   1.5049076    -1.0461128  0.6681627     -1.688942

Validación de la descomposición

valida <- cbind(geo_data$Var,
                geo_data[["Efecto fila"]] +
                geo_data[["Efecto columa"]] +
                geo_data[["Residual"]] +
                geo_data[["Efecto Global"]])
valida <- as.data.frame(valida)
names(valida) <- c("datos", "suma")
print(valida)
        datos       suma
1  -2.5276981 -2.5276981
2  -3.3094359 -3.3094359
3  -2.1348143 -2.1348143
4  -2.1178287 -2.1178287
5  -0.4909082 -0.4909082
6   1.2719638  1.2719638
7  -1.7383521 -1.7383521
8  -2.5652753 -2.5652753
9   0.1769342  0.1769342
10 -0.1281840 -0.1281840
11 -4.3067516 -4.3067516
12  0.3519380  0.3519380
13 -0.5741717 -0.5741717
14 -2.0756205 -2.0756205
15 -2.2423719 -2.2423719
16  0.9776769  0.9776769
17 -3.2540635 -3.2540635
18 -3.7658826 -3.7658826
19 -2.1071125 -2.1071125
20  0.6624249  0.6624249
21 -7.5598239 -7.5598239
22 -4.3110200 -4.3110200
23 -0.2338448 -0.2338448
24 -0.5619844 -0.5619844