Search code examples
rmatrixspatialimputationneighbours

How to impute missing neighbours of a spatial weight matrix (queen contiguity)


I have a big shape file with approx 180.000 250m^2 polygons. I want to create a spatial weight matrix (queen contiguity). So a 1 if its a neighbour, 0 otherwise. But, there are several polygons without any neighbours (islands).

How can I impute the nearest neighbour for those units that do not have any direct neighbour?

(working with sf or sp package - in R)

..........................................................................

using a sample of the data and plotting it, it would look like:

sample shape file

I can then create a W-Matrix with the following code:

Create NB List
sample_queen_nb <- poly2nb(sp.sample, row.names=sp.sample$ID, queen=T)

# Create Weights/list
sample_W.list.queen <- nb2listw(sample_queen_nb, style="W", zero.policy = TRUE) 

# Create Matrix
sample_W.queen <- listw2mat(sample_W.list.queen)

and check its connectivity with plotting it:

# Plot ShpPolygons
plot(sp.sample)
# plot weightsmatrix to see connectivity
plot(sample_queen_nb, coords, add=TRUE, col="green", cex=0.5) 

getting this:

Connectivity Matrix

As you can see - there is an island that's not connected. I would like to impute the neared neighbouring unit for this island-grid-cell. How can I do that?


Solution

  • This is what I meant by make a sample data set:

    > library(spdep);example(columbus)
    > sp.sample = columbus[c(1:5,10,23),]
    > plot(sp.sample)
    

    First lets check we have disconnected regions:

    > coords = coordinates(sp.sample)
    > queen_nb = poly2nb(sp.sample, row.names=sp.sample$ID, queen=TRUE)
    > plot(sp.sample);plot(queen_nb, coords, add=TRUE)
    

    enter image description here

    And here's a function that takes a set of region, computes the same adjacency, and then if there's any regions with no neighbours it finds the nearest neighbour and adds it to the adjacency object:

    addnbs <- function(sp.sample){
    
        queen_nb <- poly2nb(sp.sample, row.names=sp.sample$ID, queen=TRUE)
    
        count = card(queen_nb)
        if(!any(count==0)){
            return(queen_nb)
        }
    
        ## get nearest neighbour index, use centroids:
        nnbs = knearneigh(coordinates(sp.sample))$nn
    
        no_edges_from = which(count==0)
        for(i in no_edges_from){
            queen_nb[[i]] = nnbs[i]
        }
        return(queen_nb)
    }
    

    Let's test that.

    > n2 = addnbs(sp.sample)
    > plot(sp.sample);plot(n2, coords, add=TRUE)
    

    enter image description here