R: Neighbourhood contiguity by distance

dnearneigh {spdep} | R Documentation

## Neighbourhood contiguity by distance

### Description

The function identifies neighbours of region points by Euclidean distance between lower (greater than or equal to (changed from version 1.1-7)) and upper (less than or equal to) bounds, or with longlat = TRUE, by Great Circle distance in kilometers.

### Usage

    dnearneigh(x, d1, d2, row.names = NULL, longlat = NULL, bounds=c("GE", "LE"),
     use_kd_tree=TRUE, symtest=FALSE, use_s2=packageVersion("s2") > "1.0.7", k=200,
     dwithin=FALSE)

### Arguments

`x` | matrix of point coordinates, an object inheriting from SpatialPoints or an `"sf"` or `"sfc"` object; if the `"sf"` or `"sfc"` object geometries are in geographical coordinates (`use_s2=FALSE`, `sf::st_is_longlat(x) == TRUE` and `sf::sf_use_s2() == TRUE`), s2 will be used to find the neighbours because it will (we hope) use spatial indexing https://github.com/r-spatial/s2/issues/125 as opposed to the legacy method which uses brute-force (at present s2 also uses brute-force)
`d1` | lower distance bound
`d2` | upper distance bound
`row.names` | character vector of region ids to be added to the neighbours list as attribute `region.id`, default `seq(1, nrow(x))`
`longlat` | TRUE if point coordinates are longitude-latitude decimal degrees, in which case distances are measured in kilometers; if x is a SpatialPoints object, the value is taken from the object itself, and overrides this argument if not NULL
`bounds` | character vector of length 2, default `c("GE", "LE")`, (GE: greater than or equal to, LE: less than or equal to) that is the finite and closed interval `[d1, d2]`, `d1 <= x <= d2`. The first element may also be `"GT"` (GT: greater than), the second `"LT"` (LT: less than) for finite, open intervals excluding the bounds; the first bound default was changed from `"GT"` to `"GE"` in release 1.1-7. When creating multiple distance bands, finite, half-open right-closed intervals may be used until the final interval to avoid overlapping on bounds: `"GE", "LT"`, that is `[d1, d2)`, `d1 <= x < d2`
`use_kd_tree` | default TRUE, if TRUE, use dbscan `frNN` if available (permitting 3D distances).
`symtest` | Default FALSE; before release 1.1-7, TRUE - run symmetry check on output object, costly with large numbers of points.
`use_s2` | default=`packageVersion("s2") > "1.0.7"`, as of s2 > 1.0-7, distance bound computations use spatial indexing so when `sf::sf_use_s2()` is TRUE, `s2::s2_closest_edges()` will be used for distances on the sphere for `"sf"` or `"sfc"` objects if s2 > 1.0-7.
`k` | default 200, the number of closest points to consider when searching when using s2
`dwithin` | default FALSE, if TRUE, use `s2::s2_dwithin_matrix()`, both if `use_s2=TRUE`, `sf::st_is_longlat(x) == TRUE` and `sf::sf_use_s2() == TRUE`; yields the same lists of neighbours as `s2::s2_closest_edges()`.

### Value

The function returns a list of integer vectors giving the region id numbers for neighbours satisfying the distance criteria. See `card` for details of “nb” objects.

### Author(s)

Roger Bivand Roger.Bivand@nhh.no

### See Also

`knearneigh`, `card`

### Examples

    columbus <- st_read(system.file("shapes/columbus.shp", package="spData")[1], quiet=TRUE)
    coords <- st_centroid(st_geometry(columbus), of_largest_polygon=TRUE)
    rn <- row.names(columbus)
    k1 <- knn2nb(knearneigh(coords))
    all.linked <- max(unlist(nbdists(k1, coords)))
    col.nb.0.all <- dnearneigh(coords, 0, all.linked, row.names=rn)
    summary(col.nb.0.all, coords)
    opar <- par(no.readonly=TRUE)
    plot(st_geometry(columbus), border="grey", reset=FALSE,
     main=paste("Distance based neighbours 0-",  format(all.linked), sep=""))
    plot(col.nb.0.all, coords, add=TRUE)
    par(opar)
    (sfc_obj <- st_centroid(st_geometry(columbus)))
    col.nb.0.all_sf <- dnearneigh(sfc_obj, 0, all.linked, row.names=rn)
    all.equal(col.nb.0.all, col.nb.0.all_sf, check.attributes=FALSE)
    data(state)
    us48.fipsno <- read.geoda(system.file("etc/weights/us48.txt",
     package="spdep")[1])
    if (as.numeric(paste(version$major, version$minor, sep="")) < 19) {
     m50.48 <- match(us48.fipsno$"State.name", state.name)
    } else {
     m50.48 <- match(us48.fipsno$"State_name", state.name)
    }
    xy <- as.matrix(as.data.frame(state.center))[m50.48,]
    llk1 <- knn2nb(knearneigh(xy, k=1, longlat=FALSE))
    (all.linked <- max(unlist(nbdists(llk1, xy, longlat=FALSE))))
    ll.nb <- dnearneigh(xy, 0, all.linked, longlat=FALSE)
    summary(ll.nb, xy, longlat=TRUE, scale=0.5)
    gck1 <- knn2nb(knearneigh(xy, k=1, longlat=TRUE))
    (all.linked <- max(unlist(nbdists(gck1, xy, longlat=TRUE))))
    gc.nb <- dnearneigh(xy, 0, all.linked, longlat=TRUE)
    summary(gc.nb, xy, longlat=TRUE, scale=0.5)
    plot(ll.nb, xy)
    plot(diffnb(ll.nb, gc.nb), xy, add=TRUE, col="red", lty=2)
    title(main="Differences Euclidean/Great Circle")

    xy1 <- SpatialPoints((as.data.frame(state.center))[m50.48,],
      proj4string=CRS("+proj=longlat +ellps=GRS80"))
    gck1a <- knn2nb(knearneigh(xy1, k=1))
    (all.linked <- max(unlist(nbdists(gck1a, xy1))))
    gc.nb <- dnearneigh(xy1, 0, all.linked)
    summary(gc.nb, xy1, scale=0.5)

    xy1 <- st_as_sf((as.data.frame(state.center))[m50.48,], coords=1:2,
      crs=st_crs("+proj=longlat +ellps=GRS80"))
    old_use_s2 <- sf_use_s2()
    sf_use_s2(TRUE)
    gck1b <- knn2nb(knearneigh(xy1, k=1))
    system.time(o <- nbdists(gck1b, xy1))
    (all.linked <- max(unlist(o)))
    # use s2 brute-force dwithin_matrix approach
    system.time(gc.nb.dwithin <- dnearneigh(xy1, 0, all.linked, use_s2=TRUE, dwithin=TRUE))
    summary(gc.nb, xy1, scale=0.5)
    # use s2 closest_edges approach s2 > 1.0.7
    if (packageVersion("s2") > "1.0.7") {
    (system.time(gc.nb.closest <- dnearneigh(xy1, 0, all.linked, dwithin=FALSE)))
    }
    if (packageVersion("s2") > "1.0.7") {
    summary(gc.nb, xy1, scale=0.5)
    }
    # use legacy symmetric brute-force approach
    system.time(gc.nb.legacy <- dnearneigh(xy1, 0, all.linked, use_s2=FALSE))
    summary(gc.nb, xy1, scale=0.5)
    if (packageVersion("s2") > "1.0.7") all.equal(gc.nb.closest, gc.nb.dwithin, check.attributes=FALSE)
    # legacy is ellipsoidal, s2 spherical, so minor differences expected
    if (packageVersion("s2") > "1.0.7") all.equal(gc.nb, gc.nb.closest, check.attributes=FALSE)
    all.equal(gc.nb, gc.nb.dwithin, check.attributes=FALSE)
    sf_use_s2(old_use_s2)

[Package spdep version 1.2-2 Index]