How to create the adjacency weights file required to perform CAR spatial

Welcome to the forum for runmlwin users. Feel free to post your question about runmlwin here. The Centre for Multilevel Modelling take no responsibility for the accuracy of these posts, we are unable to monitor them closely. Do go ahead and post your question and thank you in advance if you find the time to post any answers!

Go to runmlwin: Running MLwiN from within Stata >> http://www.bristol.ac.uk/cmm/software/runmlwin/
Post Reply
yransome
Posts: 12
Joined: Wed Apr 22, 2015 12:07 pm

How to create the adjacency weights file required to perform CAR spatial

Post by yransome »

Dear colleagues,

I have read examples of how to perform a spatial model In runmlwin and all examples have a data set with the weights already included.
For example in the Scottish Lip Cancer example, the required variables are ( neigh1-neigh11) (weights1-weights11) and (wcar1-war11).

##My question is how does one create these variables from your own map? I have yet to find an example explaining how to do this. I got as far as creating the adjacency matrix in Winbugs/Geobugs.

Can anyone please point me on how to create those variables required to use the syntax
runmlwin obs cons perc_aff, ///
> level3(neigh1: cons, mmids(neigh1‐neigh11) mmweights(weight1‐weight11 )) ///
> level2(area:cons) ///
> level1(area:) ///
> discrete(distribution(poisson) link(log) offset(offs)) ///
> mcmc(chain(50000) refresh(500)) initsprevious nopause


## Below is the matrix the "Adjacenc Tool" created, but I am unaware how to convert that into variables


list( num = c(5, 5, 5, 4, 3, 4, 3, 3, 6, 5,
5, 5, 3, 5, 4, 4, 4, 5, 3, 4,
7, 4, 4, 7, 3, 5, 4, 5, 2, 5,
2, 4, 6, 4, 6, 4, 2, 3, 5, 3,
2, 4, 3, 6, 1, 2, 3, 3, 4, 8,
4, 4, 3, 3, 5, 6, 6, 5, 6, 7,
4, 6, 3, 1, 3, 4, 10, 5, 5, 3,
3, 4, 5, 3, 3, 8, 3, 5, 2, 4,
3, 4, 7, 6, 6, 5, 8, 6, 2, 5,
6, 5, 5, 4, 7, 7, 5, 6, 6, 4,
6, 2, 9, 3, 7, 5, 5, 5, 6, 3,
3, 6, 5, 3, 4, 6, 5, 5, 5, 2,
4, 6, 3, 6, 5, 2, 4, 8, 4, 7,
8, 3, 4, 5, 6, 5, 8, 8, 6, 4,
9, 5, 3, 4, 3, 5, 5, 7, 5, 6,
4, 4, 8, 3, 6, 4, 3, 5, 5, 6,
10, 3, 1, 2, 3, 2, 1
),
adj = c(
33, 16, 14, 10, 9,
35, 12, 11, 8, 3,
11, 10, 9, 8, 2,
82, 35, 6, 5,
35, 6, 4,
35, 7, 5, 4,
35, 12, 6,
9, 3, 2,
15, 14, 10, 8, 3, 1,
13, 11, 9, 3, 1,
13, 12, 10, 3, 2,
35, 13, 11, 7, 2,
12, 11, 10,
33, 16, 15, 9, 1,
33, 19, 16, 14,
33, 15, 14, 1,
33, 20, 19, 18,
25, 21, 20, 19, 17,
18, 17, 15,
33, 21, 18, 17,
38, 26, 25, 24, 22, 20, 18,
26, 24, 23, 21,
32, 26, 24, 22,
34, 32, 28, 27, 23, 22, 21,
38, 21, 18,
38, 32, 23, 22, 21,
36, 34, 28, 24,
36, 30, 29, 27, 24,
30, 28,
37, 36, 31, 29, 28,
37, 30,
34, 26, 24, 23,
20, 17, 16, 15, 14, 1,
36, 32, 27, 24,
12, 7, 6, 5, 4, 2,
34, 30, 28, 27,
31, 30,
26, 25, 21,
50, 48, 44, 43, 42,
50, 48, 41,
50, 40,
50, 44, 43, 39,
44, 42, 39,
50, 49, 46, 43, 42, 39,
47,
49, 44,
50, 49, 45,
50, 40, 39,
50, 47, 46, 44,
49, 48, 47, 44, 42, 41, 40, 39,
56, 55, 54, 52,
57, 56, 53, 51,
68, 57, 52,
74, 55, 51,
74, 59, 56, 54, 51,
60, 59, 57, 55, 52, 51,
68, 60, 58, 56, 53, 52,
68, 67, 60, 57, 53,
74, 73, 72, 60, 56, 55,
72, 67, 62, 59, 58, 57, 56,
69, 67, 65, 62,
73, 72, 67, 65, 61, 60,
71, 68, 67,
75,
69, 62, 61,
75, 70, 69, 67,
71, 70, 69, 68, 66, 63, 62, 61, 60, 58,
67, 63, 58, 57, 53,
75, 67, 66, 65, 61,
71, 67, 66,
70, 67, 63,
73, 62, 60, 59,
72, 65, 62, 61, 59,
59, 55, 54,
69, 66, 64,
139, 138, 116, 102, 91, 81, 79, 78,
81, 80, 78,
138, 81, 80, 77, 76,
138, 76,
138, 133, 78, 77,
78, 77, 76,
110, 97, 85, 4,
115, 113, 106, 105, 93, 92, 90,
109, 107, 103, 99, 98, 94,
117, 97, 96, 91, 86, 82,
116, 101, 96, 91, 85,
141, 116, 115, 112, 103, 101, 92, 88,
151, 147, 146, 144, 141, 87,
107, 100,
113, 109, 108, 106, 83,
139, 116, 102, 86, 85, 76,
115, 112, 93, 87, 83,
112, 105, 96, 92, 83,
107, 104, 103, 84,
117, 111, 110, 105, 99, 98, 97,
117, 112, 105, 101, 93, 86, 85,
117, 110, 95, 85, 82,
109, 106, 105, 99, 95, 84,
111, 107, 100, 98, 95, 84,
111, 107, 99, 89,
116, 112, 103, 96, 87, 86,
91, 76,
114, 112, 109, 108, 104, 101, 94, 87, 84,
114, 103, 94,
117, 106, 98, 96, 95, 93, 83,
109, 105, 98, 90, 83,
100, 99, 94, 89, 84,
114, 113, 109, 103, 90,
108, 106, 103, 98, 90, 84,
97, 95, 82,
100, 99, 95,
103, 101, 96, 93, 92, 87,
165, 115, 108, 90, 83,
108, 104, 103,
113, 92, 87, 83,
141, 139, 101, 91, 87, 86,
105, 97, 96, 95, 85,
131, 122, 121, 120, 119,
131, 130, 128, 122, 118,
121, 118,
123, 122, 120, 118,
128, 124, 123, 121, 119, 118,
124, 122, 121,
128, 127, 126, 125, 123, 122,
155, 154, 127, 126, 124,
125, 124,
155, 128, 125, 124,
155, 153, 130, 129, 127, 124, 122, 119,
158, 153, 130, 128,
161, 158, 137, 131, 129, 128, 119,
137, 136, 135, 134, 132, 130, 119, 118,
134, 133, 131,
138, 134, 132, 80,
138, 135, 133, 132, 131,
140, 139, 138, 136, 134, 131,
141, 140, 137, 135, 131,
161, 148, 145, 141, 136, 131, 130, 119,
139, 135, 134, 133, 80, 79, 78, 76,
141, 140, 138, 135, 116, 76,
141, 139, 136, 135,
151, 148, 140, 139, 137, 136, 116, 88, 87,
160, 159, 157, 153, 143,
160, 152, 142,
152, 150, 147, 88,
161, 148, 137,
151, 149, 148, 147, 88,
150, 149, 146, 144, 88,
161, 151, 149, 146, 145, 141, 137,
161, 150, 148, 147, 146,
162, 161, 152, 149, 147, 144,
148, 146, 141, 88,
160, 150, 144, 143,
159, 158, 157, 156, 155, 142, 129, 128,
156, 155, 125,
156, 154, 153, 128, 127, 125,
157, 155, 154, 153,
156, 153, 142,
161, 159, 153, 130, 129,
161, 160, 158, 153, 142,
162, 161, 159, 152, 143, 142,
162, 160, 159, 158, 150, 149, 148, 145, 137, 130,
161, 160, 150,
164,
165, 163,
166, 164, 113,
167, 165,
166
),
sumNumNeigh = 769)
ChrisCharlton
Posts: 1353
Joined: Mon Oct 19, 2009 10:34 am

Re: How to create the adjacency weights file required to perform CAR spatial

Post by ChrisCharlton »

MLwiN does not have a built-in method of doing this conversion, however as the data generated by WinBUGS appears to be in a form that can be interpreted by R you can do the conversion by writing a function such as the following in R (this assumes that you want equal weights for adjacent areas):

Code: Select all

adj2df <- function(adj) {
    idmat <- matrix(0, length(adj$num), max(adj$num))
    weightmat <- matrix(0, length(adj$num), max(adj$num))
    pos <- 1
    for (i in 1:length(adj$num)) {
        idmat[i, 1:adj$num[i]] <- adj$adj[pos:(pos+adj$num[i]-1)]
        pos <- pos + adj$num[i]
        weightmat[i, 1:adj$num[i]] <- 1 / adj$num[i] 
    }
    colnames(idmat) <- paste0("mmid", 1:ncol(idmat))
    colnames(weightmat) <- paste0("mmweight", 1:ncol(idmat))
    data.frame(cbind(idmat, weightmat))
}
You can load the data in the same format as is output by WinBUGS, assigning it to a new variable:

Code: Select all

adjdata <- list( num = c(5, 5, 5, 4, 3, 4, 3, 3, 6, 5, 
5, 5, 3, 5, 4, 4, 4, 5, 3, 4, 
7, 4, 4, 7, 3, 5, 4, 5, 2, 5, 
2, 4, 6, 4, 6, 4, 2, 3, 5, 3, 
2, 4, 3, 6, 1, 2, 3, 3, 4, 8, 
4, 4, 3, 3, 5, 6, 6, 5, 6, 7, 
4, 6, 3, 1, 3, 4, 10, 5, 5, 3, 
3, 4, 5, 3, 3, 8, 3, 5, 2, 4, 
3, 4, 7, 6, 6, 5, 8, 6, 2, 5, 
6, 5, 5, 4, 7, 7, 5, 6, 6, 4, 
6, 2, 9, 3, 7, 5, 5, 5, 6, 3, 
3, 6, 5, 3, 4, 6, 5, 5, 5, 2, 
4, 6, 3, 6, 5, 2, 4, 8, 4, 7, 
8, 3, 4, 5, 6, 5, 8, 8, 6, 4, 
9, 5, 3, 4, 3, 5, 5, 7, 5, 6, 
4, 4, 8, 3, 6, 4, 3, 5, 5, 6, 
10, 3, 1, 2, 3, 2, 1
),
adj = c(
33, 16, 14, 10, 9, 
35, 12, 11, 8, 3, 
11, 10, 9, 8, 2, 
82, 35, 6, 5, 
35, 6, 4, 
35, 7, 5, 4, 
35, 12, 6, 
9, 3, 2, 
15, 14, 10, 8, 3, 1, 
13, 11, 9, 3, 1, 
13, 12, 10, 3, 2, 
35, 13, 11, 7, 2, 
12, 11, 10, 
33, 16, 15, 9, 1, 
33, 19, 16, 14, 
33, 15, 14, 1, 
33, 20, 19, 18, 
25, 21, 20, 19, 17, 
18, 17, 15, 
33, 21, 18, 17, 
38, 26, 25, 24, 22, 20, 18, 
26, 24, 23, 21, 
32, 26, 24, 22, 
34, 32, 28, 27, 23, 22, 21, 
38, 21, 18, 
38, 32, 23, 22, 21, 
36, 34, 28, 24, 
36, 30, 29, 27, 24, 
30, 28, 
37, 36, 31, 29, 28, 
37, 30, 
34, 26, 24, 23, 
20, 17, 16, 15, 14, 1, 
36, 32, 27, 24, 
12, 7, 6, 5, 4, 2, 
34, 30, 28, 27, 
31, 30, 
26, 25, 21, 
50, 48, 44, 43, 42, 
50, 48, 41, 
50, 40, 
50, 44, 43, 39, 
44, 42, 39, 
50, 49, 46, 43, 42, 39, 
47, 
49, 44, 
50, 49, 45, 
50, 40, 39, 
50, 47, 46, 44, 
49, 48, 47, 44, 42, 41, 40, 39, 
56, 55, 54, 52, 
57, 56, 53, 51, 
68, 57, 52, 
74, 55, 51, 
74, 59, 56, 54, 51, 
60, 59, 57, 55, 52, 51, 
68, 60, 58, 56, 53, 52, 
68, 67, 60, 57, 53, 
74, 73, 72, 60, 56, 55, 
72, 67, 62, 59, 58, 57, 56, 
69, 67, 65, 62, 
73, 72, 67, 65, 61, 60, 
71, 68, 67, 
75, 
69, 62, 61, 
75, 70, 69, 67, 
71, 70, 69, 68, 66, 63, 62, 61, 60, 58, 
67, 63, 58, 57, 53, 
75, 67, 66, 65, 61, 
71, 67, 66, 
70, 67, 63, 
73, 62, 60, 59, 
72, 65, 62, 61, 59, 
59, 55, 54, 
69, 66, 64, 
139, 138, 116, 102, 91, 81, 79, 78, 
81, 80, 78, 
138, 81, 80, 77, 76, 
138, 76, 
138, 133, 78, 77, 
78, 77, 76, 
110, 97, 85, 4, 
115, 113, 106, 105, 93, 92, 90, 
109, 107, 103, 99, 98, 94, 
117, 97, 96, 91, 86, 82, 
116, 101, 96, 91, 85, 
141, 116, 115, 112, 103, 101, 92, 88, 
151, 147, 146, 144, 141, 87, 
107, 100, 
113, 109, 108, 106, 83, 
139, 116, 102, 86, 85, 76, 
115, 112, 93, 87, 83, 
112, 105, 96, 92, 83, 
107, 104, 103, 84, 
117, 111, 110, 105, 99, 98, 97, 
117, 112, 105, 101, 93, 86, 85, 
117, 110, 95, 85, 82, 
109, 106, 105, 99, 95, 84, 
111, 107, 100, 98, 95, 84, 
111, 107, 99, 89, 
116, 112, 103, 96, 87, 86, 
91, 76, 
114, 112, 109, 108, 104, 101, 94, 87, 84, 
114, 103, 94, 
117, 106, 98, 96, 95, 93, 83, 
109, 105, 98, 90, 83, 
100, 99, 94, 89, 84, 
114, 113, 109, 103, 90, 
108, 106, 103, 98, 90, 84, 
97, 95, 82, 
100, 99, 95, 
103, 101, 96, 93, 92, 87, 
165, 115, 108, 90, 83, 
108, 104, 103, 
113, 92, 87, 83, 
141, 139, 101, 91, 87, 86, 
105, 97, 96, 95, 85, 
131, 122, 121, 120, 119, 
131, 130, 128, 122, 118, 
121, 118, 
123, 122, 120, 118, 
128, 124, 123, 121, 119, 118, 
124, 122, 121, 
128, 127, 126, 125, 123, 122, 
155, 154, 127, 126, 124, 
125, 124, 
155, 128, 125, 124, 
155, 153, 130, 129, 127, 124, 122, 119, 
158, 153, 130, 128, 
161, 158, 137, 131, 129, 128, 119, 
137, 136, 135, 134, 132, 130, 119, 118, 
134, 133, 131, 
138, 134, 132, 80, 
138, 135, 133, 132, 131, 
140, 139, 138, 136, 134, 131, 
141, 140, 137, 135, 131, 
161, 148, 145, 141, 136, 131, 130, 119, 
139, 135, 134, 133, 80, 79, 78, 76, 
141, 140, 138, 135, 116, 76, 
141, 139, 136, 135, 
151, 148, 140, 139, 137, 136, 116, 88, 87, 
160, 159, 157, 153, 143, 
160, 152, 142, 
152, 150, 147, 88, 
161, 148, 137, 
151, 149, 148, 147, 88, 
150, 149, 146, 144, 88, 
161, 151, 149, 146, 145, 141, 137, 
161, 150, 148, 147, 146, 
162, 161, 152, 149, 147, 144, 
148, 146, 141, 88, 
160, 150, 144, 143, 
159, 158, 157, 156, 155, 142, 129, 128, 
156, 155, 125, 
156, 154, 153, 128, 127, 125, 
157, 155, 154, 153, 
156, 153, 142, 
161, 159, 153, 130, 129, 
161, 160, 158, 153, 142, 
162, 161, 159, 152, 143, 142, 
162, 160, 159, 158, 150, 149, 148, 145, 137, 130, 
161, 160, 150, 
164, 
165, 163, 
166, 164, 113, 
167, 165, 
166
),
sumNumNeigh = 769)
This function can then be used as follows:

Code: Select all

> adjdf <- adj2df(adjdata)
> head(adjdf)
  mmid1 mmid2 mmid3 mmid4 mmid5 mmid6 mmid7 mmid8 mmid9 mmid10 mmweight1
1    33    16    14    10     9     0     0     0     0      0 0.2000000
2    35    12    11     8     3     0     0     0     0      0 0.2000000
3    11    10     9     8     2     0     0     0     0      0 0.2000000
4    82    35     6     5     0     0     0     0     0      0 0.2500000
5    35     6     4     0     0     0     0     0     0      0 0.3333333
6    35     7     5     4     0     0     0     0     0      0 0.2500000
  mmweight2 mmweight3 mmweight4 mmweight5 mmweight6 mmweight7 mmweight8
1 0.2000000 0.2000000      0.20       0.2         0         0         0
2 0.2000000 0.2000000      0.20       0.2         0         0         0
3 0.2000000 0.2000000      0.20       0.2         0         0         0
4 0.2500000 0.2500000      0.25       0.0         0         0         0
5 0.3333333 0.3333333      0.00       0.0         0         0         0
6 0.2500000 0.2500000      0.25       0.0         0         0         0
  mmweight9 mmweight10
1         0          0
2         0          0
3         0          0
4         0          0
5         0          0
6         0          0
> require(foreign)
> write.dta(adjdf, "adj.dta")
In this example I have saved the final data as a Stata data file, which can then be merged into your Stata data or easily imported into MLwiN. I have attached this file for convenience.
Attachments
adj.dta
(29.37 KiB) Downloaded 393 times
ChrisCharlton
Posts: 1353
Joined: Mon Oct 19, 2009 10:34 am

Re: How to create the adjacency weights file required to perform CAR spatial

Post by ChrisCharlton »

Here is an alternative version of the function that sets all the weights to one for use in the CAR model:

Code: Select all

adj2df <- function(adj) {
    idmat <- matrix(0, length(adj$num), max(adj$num))
    weightmat <- matrix(0, length(adj$num), max(adj$num))
    pos <- 1
    for (i in 1:length(adj$num)) {
        idmat[i, 1:adj$num[i]] <- adj$adj[pos:(pos+adj$num[i]-1)]
        pos <- pos + adj$num[i]
        weightmat[i, 1:adj$num[i]] <- 1
    }
    colnames(idmat) <- paste0("mmid", 1:ncol(idmat))
    colnames(weightmat) <- paste0("carweight", 1:ncol(idmat))
    data.frame(cbind(idmat, weightmat))
}
This can be used in the same way:

Code: Select all

> adjdf <- adj2df(adjdata)
> head(adjdf)
  mmid1 mmid2 mmid3 mmid4 mmid5 mmid6 mmid7 mmid8 mmid9 mmid10 carweight1 carweight2 carweight3 carweight4 carweight5 carweight6
1    33    16    14    10     9     0     0     0     0      0          1          1          1          1          1          0
2    35    12    11     8     3     0     0     0     0      0          1          1          1          1          1          0
3    11    10     9     8     2     0     0     0     0      0          1          1          1          1          1          0
4    82    35     6     5     0     0     0     0     0      0          1          1          1          1          0          0
5    35     6     4     0     0     0     0     0     0      0          1          1          1          0          0          0
6    35     7     5     4     0     0     0     0     0      0          1          1          1          1          0          0
  carweight7 carweight8 carweight9 carweight10
1          0          0          0           0
2          0          0          0           0
3          0          0          0           0
4          0          0          0           0
5          0          0          0           0
6          0          0          0           0
> require(foreign)
> write.dta(adjdf, "caradj.dta")
I have again attached the generated Stata file.
Attachments
caradj.dta
(29.37 KiB) Downloaded 385 times
yransome
Posts: 12
Joined: Wed Apr 22, 2015 12:07 pm

Re: How to create the adjacency weights file required to perform CAR spatial

Post by yransome »

Dear Chris,

Thank you very much for your extended effort in providing the syntax and data. I will be sure to acknowledge your contribution in any resulting publication.

Warm regards,
Yusuf
Post Reply