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.
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