[1] 14 68 39 1 34 87 43 100 82 59
Análisis espacial con R
La autocorrelación espacial es un concepto clave en estadística espacial.
Es tanto una molestía, por que complica los test estadísticos, y una ventaja ya que permite la interpolación espacial.
La autocorrelación (sea espacial o no) es una medida de similaridad (correlación) entre observaciones cercanas.
Para entender autocorrelación espacial, ayuda primero considerar la autocorrelación temporal.
Si mides algo sobre un objeto en el tiempo, por ejemplo el peso de una persona, es probable que dos observaciones que están cerca tiene valores similares.
Digamos que tu peso en algunos años varió de 50kg a 80kg.
Es poco probable que fue de 50kg un día y al día siguiente 80kg.
El proceso debe haber sido gradual.
Para medir el grado de asociación en el tiempo, podemos calcular la correlación de cada observación con respecto a la siguiente.
Sea d
un vector de observaciones diarias
Calculamos la autocorrelación con desfase de un día
Pero es una muestra aleatoria
Calculamos la autocorrelación con un desfase de 1, para los valores inmediatamente próximos.
Si ordenamos los datos mejoramos la autocorrelación.
Si ordenamos los datos mejoramos la autocorrelación.
La función acf
muestra la autocorrelación para diferentes desfases.
El concepto de autocorrelación espacial es una extensión del de autocorrelación temporal.
Es un poco más complicado
Las mediciones de autocorrelación espacial describe el grado al cual dos observaciones en ubicaciones espaciales (sea puntos, áreas, raster) son similares.
Necesitamos observaciones y sus ubicaciones
Puede ser exógena: causada por algun otra variable autocorrelacionada
Puede ser endogena: causada por el mismo proceso (ej, covid-19)
Un estadístico usado para describir la autocorrelación espacial es el índice de Moran.
Otros son Geary
y semivariograma
library(terra)
p <- vect(system.file("external/lux.shp", package="raster"))
p <- p[p$NAME_1=="Diekirch", ]
#p$value <- c(10, 6, 4, 11, 6)
data.frame(p)
ID_1 NAME_1 ID_2 NAME_2 AREA
1 1 Diekirch 1 Clervaux 312
2 1 Diekirch 2 Diekirch 218
3 1 Diekirch 3 Redange 259
4 1 Diekirch 4 Vianden 76
5 1 Diekirch 5 Wiltz 263
Calcular la autocorrelación de la variable AREA
Debemos determinar que polígonos están cerca.
Utilizaremos adyacencia con el paquete {spdep}
.
Conección entre polígonos
Ahora podemos transforma w
a una matriz de pesos espaciales.
La matriz de pesos refleja la intensidad de la relación entre las observaciones.
\[I = \frac{n}{\sum_{i=1}^n (y_i - \bar{y})^2} \frac{\sum_{i=1}^n \sum_{j=1}^n w_{ij}(y_i - \bar{y})(y_j - \bar{y})}{\sum_{i=1}^n \sum_{j=1}^n w_{ij}}\]
Parecida a la ecuación de calculo de correlación lineal
La mayor diferencia es que agrega la matriz de pesos.
El número de observaciones
Obtenemos \(y\) e \(\bar y\)
Ahora necesitamos \((y_i - \bar{y})(y_j - \bar{y})\)
Creamos la matriz con pares multiplicados
Multiplicamos la matríz por la matriz de pesos
Ahora sumamos los valores para obtener
\[\sum_{i=1}^n \sum_{j=1}^n w_{ij}(y_i - \bar{y})(y_j - \bar{y})\]
El siguiente paso es dividir este valor por la suma de pesos
Y el inverso de la varianza
El valor del índice de Moran es
El valor esperado en ausencia de autocorrelación espacial.
\[E(I) = \frac{-1}{n-1}\]
Valores \(< E(I)\) indican autocorrelación espacial negativa
Valores \(> E(I)\) indican autocorrelación espacial positiva
En nuestro ejemplo tenemos
Y el valor del indice de Moran fue de -0.19
autocor
en el paquete terra
adjacent
.autocor
en el paquete terra
Podemos correr un análisis de significancia utilizando montecarlo/bootstraping
Graficamos para ver la autocorrelación espacial
id y value
[1,] 1 312 0
[2,] 1 312 218
[3,] 1 312 0
[4,] 1 312 76
[5,] 1 312 263
[6,] 2 218 312
[7,] 2 218 0
[8,] 2 218 259
[9,] 2 218 76
[10,] 2 218 263
[11,] 3 259 0
[12,] 3 259 218
[13,] 3 259 0
[14,] 3 259 0
[15,] 3 259 263
[16,] 4 76 312
[17,] 4 76 218
[18,] 4 76 0
[19,] 4 76 0
[20,] 4 76 0
[21,] 5 263 312
[22,] 5 263 218
[23,] 5 263 259
[24,] 5 263 0
[25,] 5 263 0
Graficamos para ver la autocorrelación espacial
El promedio en cada vecindario
El promedio en cada vecindario
Finalmente, el gráfico.
El promedio en cada vecindario
Finalmente, el gráfico.
La pendiente
ams[, 1]
-0.2302019
Otro ejemplo para clarificar
¿Cómo será el índice de Moran en cada caso?
Si miramos en los puntos de algunos de los cluster
Si miramos en los puntos de algunos de los cluster
Si miramos en los datos meuse
en la variable de concentración de copper
Si miramos en los datos meuse
en la variable de concentración de copper
Si miramos en los datos meuse
en la variable de concentración de copper
Si miramos en los datos meuse
en la variable de concentración de zinc
Si miramos en los datos meuse
en la variable de concentración de zinc
Si miramos en los datos meuse
en la variable de concentración de cadmium
Si miramos en los datos meuse
en la variable de concentración de cadmium
Generalmente hay interés en proporcionar medidas de autocorrelación local. Ej. para ver como se comporta una observación respecto a su entorno.
Local Indicators of Spatial Association (LISA)
Ii E.Ii Var.Ii Z.Ii Pr(z > E(Ii))
1 0.035611908 -0.0019483794 7.220805e-04 1.3977712 0.08109089
2 0.035940322 -0.0030238443 1.072375e-03 1.1898495 0.11705278
3 0.006105341 -0.0001921442 5.414280e-05 0.8558484 0.19604083
4 -0.001309196 -0.0002833898 6.285942e-05 -0.1293839 0.55147305
5 0.006527050 -0.0002858155 8.101434e-05 0.7569181 0.22454947
6 0.007118978 -0.0002329552 5.216030e-05 1.0179618 0.15434805
meuse_sf <- st_as_sf(meuse[c('x','y','zinc')],coords = c('x','y'),crs = 28992)
meuse_sf$Ii <- lmoran[,'Ii']
meuse_sf$Z <- lmoran[,'Z.Ii']
meuse_sf$Pr <- lmoran[, "Pr(z > E(Ii))"]
library(tmap)
p1 <- tm_shape(meuse_sf) +
tm_dots(col = "zinc", title = "Zinc", style = "quantile") +
tm_layout(legend.outside = TRUE)
p2 <- tm_shape(meuse_sf) +
tm_dots(col = "Ii", title = "Índice de Moran Local",
style = "quantile") +
tm_layout(legend.outside = TRUE)
p3 <- tm_shape(meuse_sf) +
tm_dots(col = "Z", title = "Z-score",
breaks = c(-Inf, 1.65, Inf)) +
tm_layout(legend.outside = TRUE)
p4 <- tm_shape(meuse_sf) +
tm_dots(col = "Pr", title = "p-value",
breaks = c(-Inf, 0.05, Inf)) +
tm_layout(legend.outside = TRUE)