-
Notifications
You must be signed in to change notification settings - Fork 0
/
st_manual_cut_nb.R
138 lines (125 loc) · 3.89 KB
/
st_manual_cut_nb.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#' Manual remove contiguity between two areas
#'
#' @param nb a neighbourhood `"list"` or `"matrix"`, or an `sf` dataframe with a neighbourhood column called `"nb"`.
#' @param x name or number of first area.
#' @param y name or number of second area.
#'
#' @return An amended neighbourhood `"list"`, `"matrix"`, or `sf` dataframe with a neighbourhood column called `"nb"`.
#' @export
#'
#' @examples
#' st_bridges(uk_election,"constituency_name") |>
#' st_manual_cut_nb("Ynys Mon","Arfon") |>
#' st_manual_cut_nb(292,378)
st_manual_cut_nb <- function(nb,x,y){
if (!(is.data.frame(nb) || is.list(nb$nb) || is.matrix(nb$nb) || is.list(nb) || is.matrix(nb))) {
stop("Error: The 'nb' argument must be a neighbours list, a neighbours matrix, or a dataframe containing a neighbours list or matrix named 'nb'")
} else if (is.data.frame(nb) && !("nb" %in% colnames(nb))) {
stop("Error: The dataframe must contain a column called 'nb'")
}
### case when numeric x and y:
# xnum<-x |> as.integer()
# ynum<-y |> as.integer()
if(is.numeric(x)){xnum <- x |> as.integer()}
if(is.numeric(y)){ynum <- y |> as.integer()}
### case when character x and y:
# first, make into numeric is given as character
# depending on its structure as df, list, matrix...
if(is.character(x) & is.character(y)){
if(is.data.frame(nb)){
if(is.character(x)){
if(is.list(nb$nb)){
xnum <- which(names(nb$nb)==x) |>
as.integer()
}
if(is.matrix(nb$nb)){
xnum <- which(rownames(nb$nb)==x) |>
as.integer()
}
}
if(is.character(y)){
if(is.list(nb$nb)){
ynum <- which(names(nb$nb)==y) |>
as.integer()
}
if(is.matrix(nb$nb)){
ynum <- which(rownames(nb$nb)==y) |>
as.integer()
}
}
}else{
if(is.list(nb)){
xnum <- which(names(nb)==x) |>
as.integer()
ynum <- which(names(nb)==y) |>
as.integer()
}
if(is.matrix(nb)){
xnum <- which(rownames(nb)==x) |>
as.integer()
ynum <- which(rownames(nb)==y) |>
as.integer()
}
}
}
# for cases when dataframe provided...
if(is.data.frame(nb)){
tempnb <- nb$nb # list or matrix within dataframe
if(is.matrix(tempnb)){ # matrix within dataframe
tempnb <- spdep::mat2listw(tempnb, style="B")
tempnb <- tempnb[2]
tempnb <- tempnb$neighbours
}
# class(tempnb) <- c("nb","list")
}else{
# now tempnb is a nb/list
# when just a matrix provided, tempnb becomes a list
if(is.matrix(nb)){
tempnb <- spdep::mat2listw(nb, style="B")
tempnb <- tempnb[2]
tempnb <- tempnb$neighbours
# class(tempnb) <- c("nb","list")
}
# when just a list provided, it is renamed tempnb
if(is.list(nb)){
tempnb <- nb
# class(tempnb) <- c("nb","list")
}
}
# now that tempnb has been created for different circumstances...
# if x and y are already neighbours, return original structure unchanged
if(!xnum %in% tempnb[[ynum]])
{
return(nb)
}else # else perform alteration, creating a list called tempnb
{
tempnb2 <- tempnb
tempnb2[[xnum]] <- tempnb[[xnum]][tempnb[[xnum]] !=ynum] |>
sort()
tempnb2[[ynum]] <- tempnb[[ynum]][tempnb[[ynum]] !=xnum] |>
sort()
class(tempnb2) <- c("nb","list")
if(is.data.frame(nb)){
if(is.matrix(nb$nb)){
tempmat <- spdep::nb2mat(tempnb2, style = "B")
dfmat_return <- nb
dfmat_return$nb <- tempmat
return(dfmat_return)
}
if(is.list(nb$nb)){
dflist_return <- nb
dflist_return$nb <- tempnb2
return(dflist_return)
}
}else{
# return in appropriate form
if(is.list(nb)){
return(tempnb2)
}
if(is.matrix(nb)){
tempmat <- spdep::nb2mat(tempnb2, style = "B")
return(tempmat)
}
}
}
}