[R-sig-Geo] poly2nb neighbour itself should be considered a neighbour
Robert R
u@erc@tch @end|ng |rom out|ook@com
Mon Nov 4 21:48:50 CET 2019
Dear All,
Many thanks for the proposed solutions, specially to Roger and Barry.
This was exactly what I was looking for.
I tested with a really simple polygon (see below), and it worked.
##
columbus <- sf::read_sf(system.file("etc/shapes/columbus.shp", package="spdep"))
columbus <- columbus %>% slice(1:2)
# plot(columbus)
colnn <- poly2nb(columbus)
colnn[1]
colnn[2]
# Solution 1
for(i in 1:length(colnn)){colnn[[i]]=as.integer(c(i,colnn[[i]]))}
colnn[1]
colnn[2]
# Solution 2
colnn <- include.self(colnn)
colnn[1]
colnn[2]
lw <- nb2listw(neighbours = colnn, style="W", zero.policy=TRUE)
##
Best regards,
Robert
________________________________
From: Roger Bivand <Roger.Bivand using nhh.no>
Sent: Monday, November 4, 2019 11:37
To: Barry Rowlingson <b.rowlingson using gmail.com>
Cc: Robert R <usercatch using outlook.com>; r-sig-geo using r-project.org <r-sig-geo using r-project.org>
Subject: Re: [R-sig-Geo] poly2nb neighbour itself should be considered a neighbour
On Mon, 4 Nov 2019, Barry Rowlingson wrote:
> Can you manipulate the adjacency list structure to add `i` to each list
> element vector?
>
> eg using sample data from spdep:
>
> make a neighbour structure:
>
> > colnn = poly2nb(columbus)
>
> this is a list - so for example polygon 4 is next to:
>
> > colnn[[4]]
> [1] 2 3 5 8
>
> 2, 3, 5, and 8. It seems you want to include `4` in that vector. So run
> this loop:
>
> > for(i in 1:length(colnn)){colnn[[i]]=as.integer(c(i,colnn[[i]]))}
>
> which produces a nb structure:
>
> > colnn
> Neighbour list object:
> Number of regions: 49
> Number of nonzero links: 285
> Percentage nonzero weights: 11.87005
> Average number of links: 5.816327
>
> compared with the original without self-links:
>
>> poly2nb(columbus)
> Neighbour list object:
> Number of regions: 49
> Number of nonzero links: 236
> Percentage nonzero weights: 9.829238
> Average number of links: 4.816327
>
Barry, thanks: the include.self() function:
include.self <- function(nb) {
if (!is.null(attributes(nb)$self.included) &&
(as.logical(attributes(nb)$self.included)))
stop("Self already included")
n <- length(nb)
nc <- card(nb)
for (i in 1:n) {
if (nc[i] > 0) {
nb[[i]] <- sort(c(i, nb[[i]]))
} else {
nb[[i]] <- i
}
}
attr(nb, "self.included") <- TRUE
nb
}
does this with sorting, but maybe needs class inheritance checking - it
was probably written last century.
Roger
> If you want to go on to make a weights list object:
>
>> lw = nb2listw(colnn)
>
> the neighbours are preserved:
>
>> str(lw)
> List of 3
> $ style : chr "W"
> $ neighbours:List of 49
> ..$ : int [1:3] 1 2 3
> ..$ : int [1:4] 2 1 3 4
> ..$ : int [1:5] 3 1 2 4 5
> ..$ : int [1:5] 4 2 3 5 8
> ...
> $ weights :List of 49
> ..$ : num [1:3] 0.333 0.333 0.333
> ..$ : num [1:4] 0.25 0.25 0.25 0.25
> ..$ : num [1:5] 0.2 0.2 0.2 0.2 0.2
> ..$ : num [1:5] 0.2 0.2 0.2 0.2 0.2
>
> So I think that's what you want...
>
> Note carefully the use of `as.integer` here:
>
> for(i in 1:length(colnn)){colnn[[i]]=as.integer(c(i,colnn[[i]]))}
>
> because there's code in `spdep` that expects these things to be stored as
> integer and passes them to C code. Get this wrong when manipulating
>
> > xx = poly2nb(columbus)
> > xx
> Neighbour list object:
> Number of regions: 49
> Number of nonzero links: 236
> Percentage nonzero weights: 9.829238
> Average number of links: 4.816327
> > xx[[1]] = c(1, xx[[1]])
> > xx
> Error in card(nb) :
> INTEGER() can only be applied to a 'integer', not a 'double'
>
> so instead:
>
>> xx = poly2nb(columbus)
>> xx[[1]] = as.integer(c(1, xx[[1]]))
>> xx
> Neighbour list object:
> Number of regions: 49
> Number of nonzero links: 237
> Percentage nonzero weights: 9.870887
> Average number of links: 4.836735
>
> works - I don't think its strictly necessary in the `for` loop because `i`
> is an integer but belt and braces....
>
> Barry
>
>
>
> On Sun, Nov 3, 2019 at 7:12 PM Robert R <usercatch using outlook.com> wrote:
>
>> Dear All,
>>
>> I would like to know if the function "poly2nb" ("spdep" package.) let me
>> create a neighborhood of itself, i.e., not only its queen neighbors
>> (queen=TRUE), but a neighbour itself should also be considered a neighbour.
>>
>> I am looking to create a queen weight neighborhood matrix afterwards using
>> "nb2listw".
>>
>> Any help would help me a lot.
>>
>> Many thanks
>>
>> [[alternative HTML version deleted]]
>>
>> _______________________________________________
>> R-sig-Geo mailing list
>> R-sig-Geo using r-project.org
>> https://stat.ethz.ch/mailman/listinfo/r-sig-geo
>>
>
> [[alternative HTML version deleted]]
>
> _______________________________________________
> R-sig-Geo mailing list
> R-sig-Geo using 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; e-mail: Roger.Bivand using nhh.no
https://orcid.org/0000-0003-2392-6140
https://scholar.google.no/citations?user=AWeghB0AAAAJ&hl=en
[[alternative HTML version deleted]]
More information about the R-sig-Geo
mailing list