[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