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
weightspertaining to the list of neighbors, and - a vector called
numthat gives the number of neighbors for each area.
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