200% echo everything said by Dr. Bivand below.

In addition, I would focus on the error message:

Empty neighbor sets found (zero.policy: FALSE)


This is the thing you need to solve. Why are there locations without
neighbors? A "cheap way out" which we offer in ArcGIS Pro is to provide a
union of the neighbor sets using KNN and contiguity. This ensures that each
location has at minimum k number of neighbors. You can accomplish this like
the example below. *However*, I would consider the implications of using
distance metrics for polygons. See if what you're doing actually makes
sense conceptually.

library(spdep)

geo <- system.file("shapes/columbus.gpkg", package="spData") |>
  sf::st_read(quiet = TRUE) |>
  sf::st_geometry()

nb_contig <- poly2nb(geo)

# helper from sfdep for st_centroid() -> knearneigh() -> knn2nb()
nb_k1 <- sfdep::st_knn(geo)

union.nb(nb_contig, nb_k1)

On Wed, Dec 17, 2025 at 1:06 AM Roger Bivand via R-sig-Geo <
[email protected]> wrote:

> On Tue, 16 Dec 2025, Aymard Loïc KWEKEU KWEKEU wrote:
>
> First, you do not show the versions of software being used, including the
> platform, versions of rgdal, sp, sf, spdep, mgcv, R2BayesX, possibly
> others. The versions of GDAL used in rgdal and sf may also matter, as GDAL
> also changes over time (the precision of coordinates in the same ESRI
> Shapefile may differ, artefacts in polygons bay be corrected differently).
>
> Comments inline.
>
> >
> > *Initial code with rgdal's readOGR function: *
> >
> > geo <- readOGR("./Data/Carto/COMMUNE_CARTO.shp")
>
> Without an example file (all the files making up the ESRI shapefile, at
> least *.shp, *.shx, *.dbf, preferably with *.prj), there is no way to
> establish anything.
>
> >
> > geo2 <- subset(geo, geo@data$INSEE_COM %in% selected_com)
> >
>
> Never refer to S4 slots using @ in workflows - geo$INSEE_COM has been
> sufficient now for 20 years.
>
> > DATA2BND <- sp2bnd(geo2, geo2@data$INSEE_COM)
> >
> > plot(DATA2BND)
> >
> > list_names <- as.data.frame(names(DATA2BND)) %>%
> >  group_by(names(DATA2BND)) %>%
> >  summarise(n = n())
> >
>
> sp2bnd is a function in R2BayesX and is strictly superfluous to this
> question.
>
> > nb <- mgcv:::pol2nb(DATA2BND)$nb
> >
>
> mgcv:::pol2nb is a function in mgcv and is strictly superfluous to this
> question.
>
> > W.nb <- poly2nb(
> >  geo2,
> >  row.names = rownames(geo2@data$INSEE_COM)
> > )
> >
> > w <- nb2mat(W.nb, style = "B")
>
> This is the core of the question - why no warnings or errors?
>
> >
> >
> > *New code with sf and sp: *
> >
> > geo_sf <- st_read("./Data/Carto/COMMUNE_CARTO.shp", quiet = TRUE)
>
> Coercing to an sp-class is superfluous.
>
> > geo    <- as(geo_sf, "Spatial")
> > geo2 <- subset(geo, geo@data$INSEE_COM %in% selected_com)
> >
> > DATA2BND <- sp2bnd(geo2, geo2@data$INSEE_COM)
> >
> > plot(DATA2BND)
> >
> > list_names <- as.data.frame(names(DATA2BND)) %>%
> >  group_by(names(DATA2BND)) %>%
> >  summarise(n = n())
> >
> > nb <- mgcv:::pol2nb(DATA2BND)$nb
>
> It is possible that the coordinate values of the polygons in geo2 differ
> here by a very small amount if the versions of GDAL used to install rgdal
> and sf differ, and also because sf's implementation for reading geometries
> is more modern and cleaner than that in rgdal (>20 years old).
>
> >
> > W.nb <- poly2nb(geo2, row.names = rownames(geo2@data$INSEE_COM),
> queen=T)
> > Warning messages:
> >
> > 1: In poly2nb(geo2, row.names = rownames(geo2@data$INSEE_COM), queen =
> T):
> >
> > some observations have no neighbors;
> >
> > if this seems unexpected, try increasing the snap argument.
>
> Recent changes in spdep warn about observations with no neighbours, and
> about subgraphs. Please read the relevant vignette:
> https://cran.r-project.org/web/packages/spdep/vignettes/subgraphs.html
>
> No-neighbour observations may be detected when apparently contiguous
> polygons are separated by >10mm (default value) if the input polygons are
> an sf object, otherwise sqrt(.Machine$double.eps), (so  the sp case is
> unchanged).
>
> >
> > 2: In poly2nb(geo2, row.names = rownames(geo2@data$INSEE_COM), queen =
> T):
> >
> > neighbor object has 7 sub-graphs;
> >
> > if this sub-graph count seems unexpected, try increasing the snap
> argument.
> >
> > w_SMD_2025 <- nb2mat(W.nb, style = "B")
> >
> > Error in nb2listw(neighbors, glist = glist, style = style, zero.policy =
> > zero.policy):
> >
> > Empty neighbor sets found (zero.policy: FALSE)
>
> If you accept a neighbour object with subgraphs (probably no-neighbour
> observations), set zero.policy=TRUE in nb2mat. This may however cause
> problems later on.
>
> I suggest rather avoiding sp, subsetting geo_sf, and using that object in
> poly2nb. You also need to check whether the polygons are planar or
> spherical, as this affects the default value of snap.
>
> If you need to share data, do not attach to posts on this list, but rather
> raise an issue on https://github.com/r-spatial/spdep/issues/, where the
> data and code for a minimal reproducible example may be attached.
>
> Hope this clarifies,
>
> Roger
>
> --
> Roger Bivand
> Emeritus Professor
> Department of Economics, Norwegian School of Economics,
> Postboks 3490 Ytre Sandviken, 5045 Bergen, Norway.
> e-mail: [email protected]
> _______________________________________________
> R-sig-Geo mailing list
> [email protected]
> https://stat.ethz.ch/mailman/listinfo/r-sig-geo
>

        [[alternative HTML version deleted]]

_______________________________________________
R-sig-Geo mailing list
[email protected]
https://stat.ethz.ch/mailman/listinfo/r-sig-geo

Reply via email to