2

I want to identify the specific neighbors of each polygon within a SpatialPolygonDataFrame from nb object.

enter image description here

I know I can get the number of neighbors by polygon id by card(nb), but how to get the list of the pairs? For example, something like this (in rook case):

id neighbors
1  NA
2  3,5
3  2,6,4
4  3,7
etc

My dummy data:

library(spdep)    # neighbours
library(rgdal)
library(rgeos)
library(sf)
library(raster)
library(dplyr)
library(spData)
library(sf)


# create simple reproductible example

r <- raster(nrow=6, ncol=6, crs = "+init=epsg:2957")
values(r) <- matrix(data = c(9,  NA, NA, NA, NA, NA,
                             NA, NA, NA, NA, NA, NA, 
                             NA, NA, NA, NA, NA, NA, 
                             NA, NA, NA, 1, 1, 1,
                             NA, NA, NA, 1, 9, 1,
                             NA, NA, NA, 1, 1, 1),
                    nrow = 6,
                    ncol = 6, 
                    byrow = TRUE)

Calculate neighbors:

# continuity based neighbourhood: import whole 
# shapefile, do not split it
nb <- poly2nb(polys, row.names = polys, 
                   snap = 10) # snap corrects for the gaps/slivers

Extract the number of neighbors (here, QUEEN case)

card(nb)

[1] 0 3 5 3 5 8 5 3 5 3

Merge data back:

# add number of neighbours to original polygon
polys$nb_count<- card(nb)

Get the count of neighbors by polygon:

> polys@data

   layer nb_count
1      9        0
2      1        3
3      1        5
4      1        3
5      1        5
6      9        8
7      1        5
8      1        3
9      1        5
10     1        3

Which polygons are the specific neighbors?

1

The nb object is a ragged list, so you can either get them as elements of the list:

> nb[[1]]
[1] 0
> nb[[2]]
[1] 3 5 6
> nb[[3]]
[1] 2 4 5 6 7

showing the first polygon has no neighbours, the second one connects to 3, 5, and 6, and so on.

Or convert to a full binary adjacency matrix:

> mm = nb2mat(nb,zero.policy=TRUE, style="B")
> mm
   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
1     0    0    0    0    0    0    0    0    0     0
2     0    0    1    0    1    1    0    0    0     0
3     0    1    0    1    1    1    1    0    0     0
[etc]

note this matrix is symmetric about the diagonal, so mm[3,2] is the same as mm[2,3] and tells you if polygon 2 is adjacent to polygon 3.

As a quick check, the sum across columns or rows of this matrix should be the same as card:

> apply(mm, 1, sum)
 1  2  3  4  5  6  7  8  9 10 
 0  3  5  3  5  8  5  3  5  3 
> card(nb)
 [1] 0 3 5 3 5 8 5 3 5 3
1
  • Thank you, that helped a lot. I have completely forget to simply check the nb structure using str(nb) . Now it is getting clearer – maycca Jan 24 '20 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.