Hi,
I am trying to map the bivariate spatial correlation in R (bivariate LISA). When I tried to run -- nb <- poly2nb(map)-- It is showing -- Error in poly2nb(map) : Not a polygon object.
Maybe I am doing something wrong. Please, I appreciate it if you could assist me. My code is here--
rm(list=ls(all=TRUE))
library(stringr)
library(spdep)
library(rgdal)
library(magrittr)
library(ggplot2)
library(sf)
library(sp)
library(rgdal)
library(lwgeom)
library(dplyr)
library(maptools)
library(plyr)
#======================================================
# Load data
setwd("D:/P_T/Europe")
file <-read.csv("Europe_points.csv", header = T)
Europe <-data.frame(file)
head(Europe)
#### Convert point data into spatial object
#map<-st_as_sf(Europe, coords = c("Longitude", "Latitude"), crs = 4326)
coords <- cbind(Europe$Longitude, Europe$Latitude)
eu_data <- SpatialPointsDataFrame(coords = coords, data = Europe, proj = CRS("+proj=longlat +datum=WGS84"))
## read shapefile
countries <- readOGR("D:/shape_files/ne_110m_admin_0_countries", layer="ne_110m_admin_0_countries")
sub_Europe <- countries[countries$CONTINENT == "Europe",]
#EU_proj <- spTransform(sub_Europe, CRS("+proj=longlat +datum=WGS84"))
sub_Europe@data$id <- rownames(sub_Europe@data)
# concer shp into dataframe
df_sub_Europe <-fortify(sub_Europe)
df_sub_Europe <- join(df_sub_Europe, sub_Europe@data, by="id")
## Now merge points attributes with shapefile
map <- merge(df_sub_Europe, eu_data)
# Variables to use in the correlation
x <- map[map$Variable=="Temp",]
y <- map[map$Variable=="Precip",]
#======================================================
# Some functions
# Bivariate Moran's I
moran_I <- function(x, y = NULL, W){
if(is.null(y)) y = x
xp <- scale(x)[, 1]
yp <- scale(y)[, 1]
W[which(is.na(W))] <- 0
n <- nrow(W)
global <- (xp%*%W%*%yp)/(n - 1)
local <- (xp*W%*%yp)
list(global = global, local = as.numeric(local))
}
# Permutations for the Bivariate Moran's I
simula_moran <- function(x, y = NULL, W, nsims = 2000){
if(is.null(y)) y = x
n = nrow(W)
IDs = 1:n
xp <- scale(x)[, 1]
W[which(is.na(W))] <- 0
global_sims = NULL
local_sims = matrix(NA, nrow = n, ncol=nsims)
ID_sample = sample(IDs, size = n*nsims, replace = T)
y_s = y[ID_sample]
y_s = matrix(y_s, nrow = n, ncol = nsims)
y_s <- (y_s - apply(y_s, 1, mean))/apply(y_s, 1, sd)
global_sims <- as.numeric( (xp%*%W%*%y_s)/(n - 1) )
local_sims <- (xp*W%*%y_s)
list(global_sims = global_sims,
local_sims = local_sims)
}
#======================================================
# Adjacency Matrix (Queen)
nb <- poly2nb(map)
#or #nb = st_overlaps(map,sparse=FALSE)
#nb<-st_intersects(map)
lw <-nb2listw(nb,style="B", zero.policy = TRUE)
W <- as(lw, "symmetricMatrix")
W <- as.matrix(W/rowSums(W))
W[which(is.na(W))] <- 0
#======================================================
# Calculating the index and its simulated distribution
# for global and local values
m <- moran_I(x, y, W)
# Global Moral
global_moran <- m[[1]][1]
#> 0.2218409
# Local values
m_i <- m[[2]]
# local simulations
local_sims <- simula_moran(x, y, W)$local_sims
# global pseudo p-value
# get all simulated global moran
global_sims <- simula_moran(x, y, W)$global_sims
# Proportion of simulated global values taht are higher (in absolute terms) than the actual index
moran_pvalue <- sum(abs(global_sims) > abs( global_moran )) / length(global_sims)
#> 0
# Identifying the significant values
alpha <- .05 # for a 95% confidence interval
probs <- c(alpha/2, 1-alpha/2)
intervals <- t( apply(local_sims, 1, function(x) quantile(x, probs=probs)))
sig <- ( m_i < intervals[,1] ) | ( m_i > intervals[,2] )
#======================================================
# Preparing for plotting
# Convert shape file into sf object
map_sf <- st_as_sf(map)
map_sf$sig <- sig
# Identifying the LISA clusters
xp <- scale(x)[,1]
yp <- scale(y)[,1]
patterns <- as.character( interaction(xp > 0, W%*%yp > 0) )
patterns <- patterns %>%
str_replace_all("TRUE","High") %>%
str_replace_all("FALSE","Low")
patterns[map_sf$sig==0] <- "Not significant"
map_sf$patterns <- patterns
# Rename LISA clusters
map_sf$patterns2 <- factor(map_sf$patterns, levels=c("High.High", "High.Low", "Low.High", "Low.Low", "Not significant"),
labels=c("High Temp - High Precip", "High Temp - Low Precip",
"Low Temp - High Precip", "Low Temp - Low Precip",
"Not significant"))
### PLOT
ggplot() +
geom_sf(data=map_sf, aes(fill=patterns2), color="NA") +
scale_fill_manual(values = c("red", "pink", "light blue", "dark blue", "grey80")) +
guides(fill = guide_legend(title="LISA clusters")) +
theme_minimal()
My data looks like this---
Century | Variable | Mean | Region | Latitude | Longitude | Continent |
---|---|---|---|---|---|---|
1190 | Temp | 0.35375689 | Kongressvatnet | 78.0217 | 13.9311 | Europe |
1090 | Temp | -0.345180401 | Lake Redon | 42.6425 | 0.770278 | Europe |
1190 | Temp | 0.097248967 | Lake Redon | 42.6425 | 0.770278 | Europe |
990 | Precip | -0.26756433 | Island of Grimsey | 66.5265 | -18.1957 | Europe |
1370 | Precip | 0.326454087 | Island of Grimsey | 66.5265 | -18.1957 | Europe |
990 | Precip | 1.096977506 | Island of Grimsey | 66.5265 | -18.1957 | Europe |
1370 | Precip | -1.024937192 | Island of Grimsey | 66.5265 | -18.1957 | Europe |
1090 | Temp | 1.085211722 | Seebergsee | 46.116667 | 7.466667 | Europe |
1190 | Temp | 1.347592222 | Seebergsee | 46.116667 | 7.466667 | Europe |
1370 | Temp | -2.217270397 | Seebergsee | 46.116667 | 7.466667 | Europe |
1090 | Precip | -1.400811763 | Uamh an Tartair | 58.15 | -4.983333 | Europe |
1190 | Precip | -0.092810391 | Uamh an Tartair | 58.15 | -4.983333 | Europe |
1370 | Precip | 0.638131552 | Uamh an Tartair | 58.15 | -4.983333 | Europe |
810 | Temp | -0.825153678 | Spannagel Cave | 47.09 | 11.67 | Europe |
860 | Temp | 0.5622551 | Spannagel Cave | 47.09 | 11.67 | Europe |
990 | Temp | 0.684673522 | Spannagel Cave | 47.09 | 11.67 | Europe |
1090 | Temp | 0.154193695 | Spannagel Cave | 47.09 | 11.67 | Europe |
1190 | Temp | -0.498704554 | Spannagel Cave | 47.09 | 11.67 | Europe |
1370 | Temp | -0.743541397 | Spannagel Cave | 47.09 | 11.67 | Europe |
810 | Temp | -0.230349118 | Northern inland Iberia | 42.69405 | -3.9446 | Europe |
860 | Temp | 0.044131306 | Northern inland Iberia | 42.69405 | -3.9446 | Europe |
990 | Temp | 0.335766755 | Northern inland Iberia | 42.69405 | -3.9446 | Europe |
1090 | Temp | 0.136768448 | Northern inland Iberia | 42.69405 | -3.9446 | Europe |