2

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?

Tom
  • 25
  • 5
  • First make a subset or test data set that is small enough so that you can see what is going on. You could create one from one of R's built-in spatial data sets by selecting a contiguous group and adding a couple of disjoint features. Then edit your question to show how you created that and how you are creating your spatial weights matrix currently, and how you test for connectivity. Then we can help provide a solution for that data, and the final step is to scale it up to your full data set. – Spacedman Aug 03 '19 at 06:57
  • hei - thanks, sorry, I have edited the question - do you have any idea how to impute neighbours? – Tom Aug 05 '19 at 16:13
  • Hmm things might not be that simple. What if you have two groups of polygons - every polygon has a neighbour but the whole graph is not connected. What if there are two islands? Is it okay to connect them together if they are mutual nearest neighbours? – Spacedman Aug 05 '19 at 17:56
  • yes - I need just at least one neighbour per observation. But as I need a queen-contiguity matrix for as many as possible, it should just impute the nearest neighbour for those that are not connected at all. Two groups of polygons (if they are multiple) do not need a connection to another group of polygons. I just need a connection if there is somewhere a single polygon. .... I would need a code as mine (above) and if it finds a island (one single polygon without direct neighbour) it should choose the 1-k-nearest (or sth similar). – Tom Aug 05 '19 at 18:29

1 Answers1

4

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

Spacedman
  • 92,590
  • 12
  • 140
  • 224