Skip to content

Commit 1fe0391

Browse files
author
David O'Sullivan
committed
update to spatial autocorrelation materials
1 parent 7b9e0a3 commit 1fe0391

File tree

3 files changed

+39
-38
lines changed

3 files changed

+39
-38
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22
# Spatial autocorrelation overview
33
This week simply download [this zip file](spatial-autocorrelation.zip?raw=true) and unpack it a local folder, then follow the [instructions here](assignment-spatial-autocorrelation.md).

labs/spatial-autocorrelation/assignment-spatial-autocorrelation.md

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#### GISC 422 T1 2021
1+
#### GISC 422 T2 2023
22
# **Assignment 2** Spatial autocorrelation in R and/or GeoDa
33
This assignment walks you through applying spatial autocorrelation measures, specifically Moran's index of spatial autocorrelation in both its local and global forms.
44

5-
These instructions show how these analyses can be performed in *R*, although many of you may prefer to complete the assignment using *GeoDa* which is installed on the lab machines and also free to download and install from [this website](http://geodacenter.github.io/download.html). Operation of *GeoDa* is relatively self-explanatory whereas performing these analyses in *R* using the `spdep` package is not, so you are on your own in *GeoDa*, but should find these instructions a useful overview of the methods helpful for either platform. If you work in *R* you'll find making the final report easier since you can use *R Markdown*.
5+
These instructions show how these analyses can be performed in *R*, although many of you may prefer to complete the assignment using *GeoDa* which is freely downloadable and installable on any computer from [this website](http://geodacenter.github.io/download.html). Operation of *GeoDa* is relatively self-explanatory whereas performing these analyses in *R* using the `spdep` package is not, so you are on your own in *GeoDa*, but should find these instructions a useful overview of the methods helpful for either platform. If you work in *R* you'll find making the final report easier since you can use *R Markdown*.
66

77
## Required packages
88
We need a bunch of these, so load them all now.
@@ -14,12 +14,16 @@ library(tmap)
1414
library(dplyr) # for manipulating datasets
1515
```
1616

17-
And also, the package that provides the spatial autocorrelation methods we need
17+
And also, the package that provides the spatial autocorrelation methods we need along with some helper packages
1818

1919
```{r}
2020
library(spdep)
21+
library(sp)
22+
library(maptools)
2123
```
2224

25+
There is a newer package [`sfdep`](https://sfdep.josiahparry.com/index.html) based on `spdep` which operates on `sf` data rather than older _R_-spatial formats but it still requires you to drop back to using `spdep` on occasion, so these instructions are still geared towards use of `spdep`.
26+
2327
## The data
2428
OK... now we are ready to load the data for this lab. This is a super-set of the data we previously used for the point pattern analysis lab, which includes the TB data for the old Auckland City, but extended to a wider region, and also with the additional inclusion of contemporary ethnicity data from the 2006 Census.
2529

@@ -42,39 +46,27 @@ plot(select(ak, 6:9), lwd = 0.35)
4246
Remember that we can also make maps of specific attributes as follows
4347

4448
```{r}
45-
map <- tm_shape(ak) +
49+
tm_shape(ak) +
4650
tm_fill(col = "EUR_P_06", palette = 'Blues') + # add colour fill
47-
tm_borders(col = 'gray', lwd = 0.5) # add borders to the polygons
48-
map
49-
```
50-
51-
Remember also that if we want an interactive web map, we can change the `tmap` mode to `"view"`
52-
53-
```{r}
54-
tmap_mode("view")
55-
map
56-
```
57-
58-
For now, we probably don't need interactive web maps, so change back to `"plot"` mode and make sure everything is still good to go
59-
60-
```{r}
61-
tmap_mode("plot")
62-
map
51+
tm_borders(col = 'gray', lwd = 0.5) + # add borders to the polygons
52+
tm_legend(position = c("left", "top"))
6353
```
6454

6555
## Back to spatial autocorrelation
66-
The functions discussed in this section and the remainder of these instructions are provided by the `spdep` package. This is an older package, which can work with `sf` objects but with some difficulty, so it is easier to make a `sp` package compatible `SpatialPolygonsDataFrame` object from our data for some of the operations to follow. We'll call this `akp` and will use the original `ak` object where it is more convenient, but work with `akp` when needed.
56+
The functions discussed in this section and the remainder of these instructions are provided by the `spdep` package. This is an older package, which can work with `sf` objects but with some difficulty, so it is easier to make a `sp` package compatible `SpatialPolygonsDataFrame` object from our data for some of the operations that follow. We'll call this `aksp` and will use the original `ak` object where it is more convenient, but work with `aksp` when needed.
6757

6858
```{r}
69-
akp <- as_Spatial(ak)
59+
aksp <- ak %>%
60+
as("Spatial")
7061
```
7162

72-
Since `akp` and `ak` are derived from the same underlying data and retain the same *order* of entries in their data tables, we shouldn't run into any problems.
63+
Since `aksp` and `ak` are derived from the same underlying data and retain the same *order* of entries in their data tables, we shouldn't run into any problems.
7364

7465
The main reason for making this object is that the key functions of `spdep` require the construction of *neighbourhoods* for each polygon in the dataset, on which the autocorrelation calculations will be based. The most basic neighbourhood construction is based on adjacency and is generated using the `poly2nb()` function. This is how it works
7566

7667
```{r}
77-
nb <- poly2nb(akp, row.names = ak$AU_NAME, queen = TRUE)
68+
nb <- aksp %>%
69+
poly2nb(row.names = ak$AU_NAME, queen = TRUE)
7870
```
7971

8072
We can inspect what we just did, with the `summary()` function
@@ -88,28 +80,34 @@ We can see here that we made a neighbourhood object that has 1612 adjacency link
8880
To get a better idea what is going on we can map these
8981

9082
```{r}
91-
plot(akp, col = "lightgrey", lwd = 0.5, border = 'white')
92-
plot(nb, coordinates(akp), col = 'red', lwd = 0.5, cex = 0.35, add = T)
83+
plot(aksp, col = "lightgrey", lwd = 0.5, border = 'white')
84+
85+
# make a set of centroid coordinate points for convenience
86+
ak_pts <- sp::coordinates(aksp)
87+
88+
plot(nb, ak_pts, col = 'red', lwd = 0.5, cex = 0.35, add = T)
9389
```
9490

9591
At this point, you should experiment with the `poly2nb` function (what happens if you set `queen = FALSE`?).
9692

9793
### Other neighborhood construction methods
98-
It is possible to construct neighbourhoods on other bases, such as for example, the k nearest neighbours approach. This is unfortunately where the `spdep` package shows its age, because doing so is fiddly. Here is how it works, just as an example, that you are welcome to explore further.
94+
It is possible to construct neighbourhoods on other bases, such as for example, the _k_ nearest neighbours approach. This is unfortunately where the `spdep` package shows its age, because doing so is fiddly. Here is how it works, just as an example, that you are welcome to explore further.
9995

10096
```{r}
101-
ak_k5 <- knearneigh(coordinates(akp), k = 5)
102-
nb_k5 <- knn2nb(ak_k5)
103-
plot(akp, col = "lightgrey", lwd = 0.5, border = 'white')
104-
plot(nb_k5, coordinates(akp), cex = 0.35, lwd = 0.5, col = 'red', add = T)
97+
nb_k5 <- ak_pts %>%
98+
knearneigh(k = 5) %>%
99+
knn2nb()
100+
plot(aksp, col = "lightgrey", lwd = 0.5, border = 'white')
101+
plot(nb_k5, ak_pts, cex = 0.35, lwd = 0.5, col = 'red', add = T)
105102
```
106103

107104
Or another alternative is to use a distance criterion
108105

109106
```{r}
110-
nb_d2500 <- dnearneigh(coordinates(akp), d1 = 100, d2 = 2500)
111-
plot(akp, col = "lightgrey", lwd = 0.5, border = 'white')
112-
plot(nb_d2500, coordinates(akp), cex = 0.35, lwd = 0.5, col = 'red', add = T)
107+
nb_d2500 <- ak_pts %>%
108+
dnearneigh(d1 = 0, d2 = 2500)
109+
plot(aksp, col = "lightgrey", lwd = 0.5, border = 'white')
110+
plot(nb_d2500, ak_pts, cex = 0.35, lwd = 0.5, col = 'red', add = T)
113111
```
114112

115113
You can probably see here why I say that the `spdep` functions are a bit obscure to work with. Anyway, let's return to doing the analysis based on simple adjacency, as recorded in the `nb` object we made before.
@@ -120,7 +118,8 @@ Something to pay attention to from here forward is that many of the Moran's inde
120118
Another quirk of the `spdep` package is that it requires the neighbourhood information in a particular format to work, and this is *not* the format that the various neighbourhood construction methods produce. To get the right format we must convert the neighbourhood information to a `listw` object
121119

122120
```{r}
123-
wl <- nb2listw(nb, style = "W", zero.policy = T)
121+
wl <- nb %>%
122+
nb2listw(style = "W", zero.policy = TRUE)
124123
summary(wl, zero.policy = T)
125124
```
126125

@@ -130,7 +129,8 @@ As you can see (and reassuringly!) this object has exactly the same characterist
130129
After all that, the moment of truth is very simple. We can calculate the value of Moran's index. The permutation approach discussed in lectures is the most appropriate way to put some kind of statistical limits on the result for interpretive purposes. This is invoked by `moran.mc()`
131130

132131
```{r}
133-
moransI <- moran.mc(ak$ASI_P_06, wl, nsim = 999, zero.policy = T)
132+
moransI <- ak$ASI_P_06 %>%
133+
moran.mc(wl, nsim = 999, zero.policy = TRUE)
134134
moransI
135135
```
136136

@@ -152,7 +152,8 @@ What do you think the gray circle represents in the plot?
152152
Finally, we can also calculate the local version of Moran's *I*.
153153

154154
```{r}
155-
localm <- localmoran(ak$ASI_P_06, wl, zero.policy = T)
155+
localm <- ak$ASI_P_06 %>%
156+
localmoran(wl, zero.policy = TRUE)
156157
head(localm)
157158
```
158159

5.92 KB
Binary file not shown.

0 commit comments

Comments
 (0)