[R-sig-Geo] Moran.I function in "ape" library yielding unexpected values

Roger Bivand Roger.Bivand at nhh.no
Fri Dec 5 15:03:30 CET 2014


On Fri, 5 Dec 2014, Steve Pickering wrote:

> Dear r-sig-geo community,
>
> I'm running the Moran.I function in the "ape" library and getting some
> values which are not what I'm expecting.  Consider the code below, in
> which a simple 8 x 8 grid is set up, and then populated with a
> chessboard pattern.  My understanding is that a chessboard is an
> example of perfect negative spatial autocorrelation, and that it
> should therefore yield a Moran's I value of -1.  The result it yields,
> while negative, is not close to -1:
>
> $observed
> [1] -0.07775248
>
> $expected
> [1] -0.01587302
>
> $sd
> [1] 0.01499786
>
> $p.value
> [1] 3.693094e-05
>
> The code is as follows.  Can anyone tell me what I'm doing wrong?

Your definition of all observations as neighbours of each other is causing 
this result. It isn't wrong, but very often the choice of weights will 
have an effect. Try:

library(spdep)
nb8r <- cell2nb(8, 8, type="rook", torus=FALSE)
nb8q <- cell2nb(8, 8, type="queen", torus=FALSE)
nb8rt <- cell2nb(8, 8, type="rook", torus=TRUE)
nb8qt <- cell2nb(8, 8, type="queen", torus=TRUE)

moran.test(testGrid$chess, nb2listw(nb8r, style="B"),
   alternative="two.sided")
# -1.000000000
moran.test(testGrid$chess, nb2listw(nb8q, style="B"),
   alternative="two.sided")
# -0.066666667
moran.test(testGrid$chess, nb2listw(nb8rt, style="B"),
   alternative="two.sided")
# -1.000000000
moran.test(testGrid$chess, nb2listw(nb8qt, style="B"),
   alternative="two.sided")
# 0.000000000

rdists <- nbdists(nb8r, cbind(testGrid$lng, testGrid$lat))
irdists <- lapply(rdists, function(x) 1/x)
qdists <- nbdists(nb8q, cbind(testGrid$lng, testGrid$lat))
iqdists <- lapply(qdists, function(x) 1/x)

moran.test(testGrid$chess, nb2listw(nb8r, glist=irdists, style="B"),
   alternative="two.sided")
# -1.000000000
moran.test(testGrid$chess, nb2listw(nb8q, glist=iqdists, style="B"),
   alternative="two.sided")
# -0.235545329

nb8all <- dnearneigh(cbind(testGrid$lng, testGrid$lat), 0,
   sqrt(2*(7^2)))
alldist <- nbdists(nb8all, cbind(testGrid$lng, testGrid$lat))
ialldist <- lapply(alldist, function(x) 1/x)
summary(rowSums(testGrid.dists.inv))
summary(sapply(ialldist, sum))
moran.test(testGrid$chess, nb2listw(nb8all, glist=ialldist, style="B"),
   randomisation=TRUE, alternative="two.sided")
# -0.0769782624

So the design of the spatial weights is driving the outcome. In addition, 
the 0/1 nature of the data is not strictly appropriate for Moran's I, 
which could take the residuals of a glm():

mod <- glm(chess ~ 1, data=testGrid, family=binomial)
lm.morantest(mod, nb2listw(nb8rt, style="B"), alternative="two.sided")
# -1.00000000

or join-count tests:

joincount.multi(as.factor(testGrid$chess), nb2listw(nb8r, style="B"))
#      Joincount Expected Variance z-value
# 0:0      0.000   27.556    8.325 -9.5503
# 1:1      0.000   27.556    8.325 -9.5503
# 1:0    112.000   56.889   27.205 10.5662
# Jtot   112.000   56.889   27.205 10.5662

joincount.multi(as.factor(testGrid$chess), nb2listw(nb8q, style="B"))
#      Joincount Expected Variance z-value
# 0:0     49.000   51.667   23.616 -0.5487
# 1:1     49.000   51.667   23.616 -0.5487
# 1:0    112.000  106.667   47.796  0.7714
# Jtot   112.000  106.667   47.796  0.7714

joincount.multi(as.factor(testGrid$chess), nb2listw(nb8all, 
glist=ialldist, style="B"))
#      Joincount Expected Variance z-value
# 0:0    148.864  158.719   34.009 -1.6899
# 1:1    148.864  158.719   34.009 -1.6899
# 1:0    347.388  327.678   22.506  4.1547
# Jtot   347.388  327.678   22.506  4.1547

In the rook case, there are no 0:0 or 1:1 joins, but there are in the 
Queen and all-in inverted distance cases.

I'm not sure that this clarifies, but it does account for your result.

Roger

>
> As always, many thanks!
>
> - Steve.
>
>
>
> library(ape)
>
> # first, build an 8 x 8 grid
> # lats and lngs will go from 0 to 7
>
> lng <- rep(seq(0, 7, by=1), 8)
>
> counter = 1
> subCounter = 0
> startNum = 0
> lat = NULL
>
> while (counter < 65) {
>
> if (subCounter == 8) {
> startNum = startNum + 1
> subCounter = 0
> }
>
> lat = c(lat, startNum)
> subCounter = subCounter + 1
> counter = counter + 1
>
> }
>
> # now add the black/ white chessboard pattern
>
> chess <- rep(c(0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0), 4)
>
> gridNum <- seq(1:64)
>
> testGrid <- data.frame(gridNum, lat, lng, chess)
>
> # simple Euclidean distance measure
>
> testGrid.dists <- as.matrix(dist(cbind(testGrid$lng, testGrid$lat)))
>
> # invert the distances, then replace the infinities with 0
>
> testGrid.dists.inv <- 1 / testGrid.dists
>
> diag(testGrid.dists.inv) <- 0
>
> # now test the chessboard pattern
>
> Moran.I(testGrid$chess, testGrid.dists.inv)
>
>
>
> Steve Pickering
> Assistant Professor
> Graduate School of Law
> Kobe University
> 2-1 Rokkodai-cho
> Nada-ku, Kobe
> 657-8501 Japan
> pickering at penguin.kobe-u.ac.jp
> http://www.stevepickering.net
>
> _______________________________________________
> R-sig-Geo mailing list
> R-sig-Geo at r-project.org
> https://stat.ethz.ch/mailman/listinfo/r-sig-geo
>

-- 
Roger Bivand
Department of Economics, Norwegian School of Economics,
Helleveien 30, N-5045 Bergen, Norway.
voice: +47 55 95 93 55; fax +47 55 95 91 00
e-mail: Roger.Bivand at nhh.no



More information about the R-sig-Geo mailing list