Defining Neighbors, Creating Weight Matrices

This entry outlines a few procedures that come with the spdep package. All commands have options, but most of these are not mentioned here.

Neighbors

Neighbors will typically be created from a spatial polygon file. Neighbors can be based on contiguity, distance, or the k nearest neighbors may be defined. Finally, second or third order neighbors can be defined.

Contiguity

The basic command is poly2nb.

library(spdep)
my-neighborhood.nb <- poly2nb(my-spatial-polygon-data)

This will create a queen contiguity matrix (a single common point will suffice to define two polygons as neighbors). Optionally, a rook matrix may be requested.

Distance

The basic command is dnearneigh. Note that the result again is a (possibly normalized) matrix of "yes/no" (neighbor or no neighbor). For creating an inverse distance matrix see below!

k nearest neighbors

Unsurprisingly, the command is knearneigh.

Higher order neighbors

Use the nblag command. As yet I have not found the time (or the occasion) to try this.

Weight oder Distance Matrices

Matrices for spdep package

Once you have created a neighborhood object, a weight matrix can easily be created with nb2listw. This matrix is added to the neighborhood object; thus, the new object has two classes, nb and listw. In other words, it is not a simple matrix; rather, the information is stored in a way that is useful for procedures from the spdep package or related spatial packages by Roger Bivand et al.

nbweights.lw <- nb2listw(nb-object, style="W", zero.policy=T)

I have added two options: style="W" creates a row-normalized (or standardized) matrix, whereas zero.policy=T ensures that the matrix is computed even if there are "islands", that is, no-neighbor areas. Of course it's up to you to decide whether this is what you want.

An lw object may also be created from any (symmetric) matrix as follows:

lw-object.lw <- mat2listw(some-matrix, style="W")

'Classic' matrices

For whatever reason, you may wish to have your weight matrix represented as a 'normal' matrix (a class matrix object), not as an object of a special/spatial class.

my-matrix <- nb2mat(my-nb-object)

will transform an nb object (i.e. a neighborhood object) into a matrix. You may add , style = "W" to obtain a row-standardized matrix.

my-matrix <- listw2mat(my-lw-object)

will transform an lw object (i.e. a weight matrix created with the nb2listw command) into a matrix. There is no option for row-standardization, as row-standardization can be achieved in the process of creating the lw object.

Inverse distance matrices

I think this is fairly easy, as the nbdists command from spdep computes the distances for the neighbors in an nb object. However, some further manipulation will be required to obtain an (inverse) distance matrix. I found it easier to use the package fields, which must be installed first. Once this has been accomplished, proceed as follows:

library(field)
mycoords <- coordinates(my-spatial-polygon-datafile)
mydm <- rdist.earth(mycoords)            # computes distance in miles!
for(i in 1:dim(mydm)[1]) {mydm[i,i] = 0} # renders exactly zero all diagonal elements
mydm[mydm > 1000] <- 0                   # all distances > 1000 miles are set to zero
mydm <- ifelse(mydm!=0, 1/mydm, mydm)    # inverting distances
mydm.lw <- mat2listw(mydm, style="W")    # create a (normalized) listw object
mydmi <- listw2mat(mydm.lw)              # change back to 'classic' matrix, if desired

Special: Spatial Information for WinBUGS/OpenBUGS

The car.normal function implemented in WinBUGS/OpenBUGS and related functions require spatial information as follows:

  • A list of neighbors supplied as a vector called adj,
  • a list of weights appropriately called weights pertaining to the list of neighbors, and
  • a vector called num that gives the number of neighbors for each area.
Note that the weights should not be standardized (or normalized).

As yet, I am too dumb to create these objects in a fully standardized way, but it's still fairly simple as follows:

Create a list containing the three elements just outlined from an nb object with

mynblist <- nb2WB(neighbors.nb)

Next, extract the three elements:

nb.a <- mynblist[1]
nb.w <- mynblist[2]
nb.n <- mynblist[3]

However, the three new objects, even though being vectors, are still of the class list. This can be changed as follows:

adjb <- dput(nb.a,control=NULL)
weightb <- dput(nb.w,control=NULL)
numb <- dput(nb.n,control=NULL)

The results of these three commands in the console correspond almost exactly to the three objects we need. All that needs to be done is to copy the output into your script, omitting the beginning "list(" and the closing ")".

But note that if the weights are just a series of ones, you can create the required object as follows:

weights <- rep(1,length(adj))

This command will store a vector of ones of the desired length to object "weights".

© W. Ludwig-Mayerhofer, R Guide | Last update: 28 Nov 2016