diff --git a/NAMESPACE b/NAMESPACE index 0947d07b..2c48f6e5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -83,7 +83,8 @@ export(grid2nb) export(autocov_dist) export(set.VerboseOption, get.VerboseOption, set.ZeroPolicyOption, - get.ZeroPolicyOption, get.SubgraphOption, set.SubgraphOption) + get.ZeroPolicyOption, get.SubgraphOption, set.SubgraphOption, + get.SubgraphCeiling, set.SubgraphCeiling) export(set.mcOption, get.mcOption, set.coresOption, get.coresOption, set.ClusterOption, get.ClusterOption) diff --git a/R/AAA.R b/R/AAA.R index 818d7c3e..90859400 100644 --- a/R/AAA.R +++ b/R/AAA.R @@ -12,7 +12,9 @@ assign("cores", NULL, envir = .spdepOptions) assign("cluster", NULL, envir = .spdepOptions) assign("rlecuyerSeed", rep(12345, 6), envir = .spdepOptions) assign("listw_is_CsparseMatrix", FALSE, envir = .spdepOptions) - +assign("cluster", NULL, envir = .spdepOptions) +assign("report_nb_subgraphs", TRUE, envir = .spdepOptions) +assign("nb_subgraphs_N+E", 100000L, envir = .spdepOptions) setOldClass(c("listw")) .onLoad <- function(lib, pkg) { diff --git a/R/components.R b/R/components.R index 1534a3b0..09fad2aa 100644 --- a/R/components.R +++ b/R/components.R @@ -2,16 +2,16 @@ # -n.comp.nb <- function(nb.obj, igraph=FALSE){ - if(!inherits(nb.obj,"nb"))stop("not a neighbours list") - stopifnot(is.logical(igraph)) - stopifnot(length(igraph) == 1L) +n.comp.nb <- function(nb.obj){ + if(!inherits(nb.obj,"nb")) stop("not a neighbours list") + if (sum(card(nb.obj)) == 0L) { + return(list(nc=length(nb.obj), comp.id=1:length(nb.obj))) + } nb.sym <- is.symmetric.nb(nb.obj) - if (igraph) { - if (!requireNamespace("igraph", quietly=TRUE)) { - igraph <- !igraph - warning("igraph not available, set FALSE") - } + igraph <- FALSE + if (requireNamespace("igraph", quietly=TRUE) && + requireNamespace("spatialreg", quietly=TRUE)) { + igraph <- TRUE } if (!igraph) { if (!nb.sym) nb.obj <- make.sym.nb(nb.obj) @@ -22,11 +22,10 @@ n.comp.nb <- function(nb.obj, igraph=FALSE){ stopifnot(requireNamespace("igraph", quietly=TRUE)) stopifnot(requireNamespace("spatialreg", quietly=TRUE)) B <- as(nb2listw(nb.obj, style="B", zero.policy=TRUE), "CsparseMatrix") - g1 <- igraph::graph_from_adjacency_matrix(B, mode=ifelse(nb.sym, "undirected", "directed")) c1 <- igraph::components(g1, mode="weak") - answ <- list(nc=c1$no, comp.id=c1$membership) + answ <- list(nc=c1$no, comp.id=unname(c1$membership)) } answ } diff --git a/R/diffnb.R b/R/diffnb.R index 72cdbb80..57174613 100644 --- a/R/diffnb.R +++ b/R/diffnb.R @@ -31,9 +31,11 @@ diffnb <- function(x, y, verbose=NULL) { attr(res, "region.id") <- attr(x, "region.id") attr(res, "call") <- match.call() res <- sym.attr.nb(res) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(res)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- n + sum(card(res)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(res) + attr(res, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } res } diff --git a/R/dnearneigh.R b/R/dnearneigh.R index 07bb977e..1cd45ee1 100644 --- a/R/dnearneigh.R +++ b/R/dnearneigh.R @@ -124,9 +124,11 @@ dnearneigh <- function(x, d1, d2, row.names=NULL, longlat=NULL, bounds=c("GE", " attr(z, "nbtype") <- "distance" if (symtest) z <- sym.attr.nb(z) else attr(z, "sym") <- TRUE - if (get.SubgraphOption()) { - nsg <- n.comp.nb(z)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- np + sum(card(z)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(z) + attr(z, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } z } diff --git a/R/droplinks.R b/R/droplinks.R index 4f6ecda0..29261686 100644 --- a/R/droplinks.R +++ b/R/droplinks.R @@ -30,9 +30,11 @@ droplinks <- function(nb, drop, sym=TRUE) { nb[[i]] <- 0L } nb <- sym.attr.nb(nb) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(nb)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- n + sum(card(nb)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(nb) + attr(nb, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } nb } diff --git a/R/edit.nb.R b/R/edit.nb.R index f60ab01d..d8d1a22f 100644 --- a/R/edit.nb.R +++ b/R/edit.nb.R @@ -162,9 +162,11 @@ edit.nb <- function(name, coords, polys=NULL, ..., use_region.id=FALSE) { if (is.null(icl)) class(nb) <- "nb" else class(nb) <- c("nb", icl) nb <- sym.attr.nb(nb) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(nb)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- n + sum(card(nb)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(nb) + attr(z, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } nb } diff --git a/R/graph2nb.R b/R/graph2nb.R index b6572d17..90b6d712 100644 --- a/R/graph2nb.R +++ b/R/graph2nb.R @@ -31,9 +31,11 @@ graph2nb <- function(gob, row.names=NULL,sym=FALSE) { attr(res, "type") <- attr(gob, "type") class(res) <- "nb" res <- sym.attr.nb(res) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(res)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(res) + sum(card(res)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(res) + attr(res, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } res } diff --git a/R/knn2nb.R b/R/knn2nb.R index cc44f5b6..b98d9172 100644 --- a/R/knn2nb.R +++ b/R/knn2nb.R @@ -27,9 +27,11 @@ knn2nb <- function(knn, row.names=NULL, sym=FALSE) { attr(res, "type") <- "knn" attr(res, "knn-k") <- knn$k class(res) <- "nb" - if (get.SubgraphOption()) { - nsg <- n.comp.nb(res)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(res) + sum(card(res)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(res) + attr(res, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } res } diff --git a/R/nb2blocknb.R b/R/nb2blocknb.R index 8a2897f1..5b0d638f 100644 --- a/R/nb2blocknb.R +++ b/R/nb2blocknb.R @@ -47,9 +47,11 @@ nb2blocknb <- function(nb=NULL, ID, row.names = NULL) { attr(res, "block") <- TRUE attr(res, "call") <- match.call() res <- sym.attr.nb(res) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(res)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(res) + sum(card(res)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(res) + attr(res, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } res } diff --git a/R/nblag.R b/R/nblag.R index 1b70f720..575763ab 100644 --- a/R/nblag.R +++ b/R/nblag.R @@ -38,10 +38,12 @@ nblag <- function(neighbours, maxlag) class(lags[[i]]) <- "nb" attr(lags[[i]], "region.id") <- attr(neighbours, "region.id") lags[[i]] <- sym.attr.nb(lags[[i]]) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(lags[[i]])$nc - if (nsg > 1) - warning("neighbour object ", i, " has ", nsg, " sub-graphs") + NE <- length(lags[[i]]) + sum(card(lags[[i]])) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(lags[[i]]) + attr(lags[[i]], "ncomp") <- ncomp + if (ncomp$nc > 1) warning("lag ", i, + " neighbour object has ", ncomp$nc, " sub-graphs") } } attr(lags, "call") <- match.call() diff --git a/R/nboperations.R b/R/nboperations.R index e76c2355..84ef50fd 100644 --- a/R/nboperations.R +++ b/R/nboperations.R @@ -28,9 +28,11 @@ union.nb<-function(nb.obj1, nb.obj2){ attr(new.nb,"type")<-paste("union(",attr(nb.obj1,"type"), ",",attr(nb.obj2,"type"),")") class(new.nb)<-"nb" - if (get.SubgraphOption()) { - nsg <- n.comp.nb(new.nb)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(new.nb) + sum(card(new.nb)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(new.nb) + attr(new.nb, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } new.nb } @@ -59,9 +61,11 @@ intersect.nb<-function(nb.obj1, nb.obj2){ attr(new.nb,"type")<-paste("intersect(",attr(nb.obj1,"type"), ",",attr(nb.obj2,"type"),")") class(new.nb)<-"nb" - if (get.SubgraphOption()) { - nsg <- n.comp.nb(new.nb)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(new.nb) + sum(card(new.nb)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(new.nb) + attr(new.nb, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } new.nb } @@ -107,9 +111,11 @@ setdiff.nb<-function(nb.obj1, nb.obj2){ attr(new.nb,"type")<-paste("setdiff(",attr(nb.obj1,"type"), ",",attr(nb.obj2,"type"),")") class(new.nb)<-"nb" - if (get.SubgraphOption()) { - nsg <- n.comp.nb(new.nb)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(new.nb) + sum(card(new.nb)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(new.nb) + attr(new.nb, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } new.nb } @@ -134,9 +140,11 @@ complement.nb<-function(nb.obj){ } attr(new.nb,"type")<-paste("complement(",attr(nb.obj,"type"),")") class(new.nb)<-"nb" - if (get.SubgraphOption()) { - nsg <- n.comp.nb(new.nb)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(new.nb) + sum(card(new.nb)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(new.nb) + attr(new.nb, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } new.nb } diff --git a/R/poly2nb.R b/R/poly2nb.R index fa83c553..ec4edc2f 100644 --- a/R/poly2nb.R +++ b/R/poly2nb.R @@ -200,9 +200,11 @@ poly2nb <- function(pl, row.names=NULL, snap=sqrt(.Machine$double.eps), if (queen) attr(ans, "type") <- "queen" else attr(ans, "type") <- "rook" ans <- sym.attr.nb(ans) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(ans)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- n + sum(card(ans)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(ans) + attr(ans, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } if (verbose) cat("done:", (proc.time() - .ptime_start)[3], "\n") .ptime_start <- proc.time() diff --git a/R/read.gal.R b/R/read.gal.R index 4afc3724..97d8f767 100644 --- a/R/read.gal.R +++ b/R/read.gal.R @@ -64,9 +64,11 @@ read.gal <- function(file, region.id=NULL, override.id=FALSE) attr(res1, "gal") <- TRUE attr(res1, "call") <- TRUE res1 <- sym.attr.nb(res1) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(res1)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(res1) + sum(card(res1)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(res1) + attr(res1, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } res1 } diff --git a/R/read.gwt2nb.R b/R/read.gwt2nb.R index eb6101fb..72f40125 100644 --- a/R/read.gwt2nb.R +++ b/R/read.gwt2nb.R @@ -72,9 +72,11 @@ read.gwt2nb <- function(file, region.id=NULL) { attr(res, "call") <- match.call() attr(res, "n") <- n res <- sym.attr.nb(res) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(res)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- length(res) + sum(card(res)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(res) + attr(res, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } res } diff --git a/R/spChkOption.R b/R/spChkOption.R index b5e6bda3..9703b7df 100644 --- a/R/spChkOption.R +++ b/R/spChkOption.R @@ -1,10 +1,10 @@ -# Copyright 2003-2015 by Roger Bivand +# Copyright 2003-2024 by Roger Bivand set.listw_is_CsparseMatrix_Option <- function(check) { if (!is.logical(check)) stop ("logical argument required") res <- get("listw_is_CsparseMatrix", envir = .spdepOptions) assign("listw_is_CsparseMatrix", check, envir = .spdepOptions) - res + invisible(res) } get.listw_is_CsparseMatrix_Option <- function() { @@ -15,7 +15,7 @@ set.spChkOption <- function(check) { if (!is.logical(check)) stop ("logical argument required") res <- get("spChkID", envir = .spdepOptions) assign("spChkID", check, envir = .spdepOptions) - res + invisible(res) } get.spChkOption <- function() { @@ -26,7 +26,7 @@ set.VerboseOption <- function(check) { if (!is.logical(check)) stop ("logical argument required") res <- get("verbose", envir = .spdepOptions) assign("verbose", check, envir = .spdepOptions) - res + invisible(res) } get.SubgraphOption <- function() { @@ -37,9 +37,21 @@ set.SubgraphOption <- function(check) { if (!is.logical(check)) stop ("logical argument required") res <- get("report_nb_subgraphs", envir = .spdepOptions) assign("report_nb_subgraphs", check, envir = .spdepOptions) - res + invisible(res) +} + +get.SubgraphCeiling <- function() { + get("nb_subgraphs_N+E", envir = .spdepOptions) } +set.SubgraphCeiling <- function(value) { + if (!is.integer(value)) stop ("integer argument required") + res <- get("nb_subgraphs_N+E", envir = .spdepOptions) + assign("nb_subgraphs_N+E", value, envir = .spdepOptions) + invisible(res) +} + + get.VerboseOption <- function() { get("verbose", envir = .spdepOptions) } @@ -48,7 +60,7 @@ set.ZeroPolicyOption <- function(check) { if (!is.logical(check)) stop ("logical argument required") res <- get("zeroPolicy", envir = .spdepOptions) assign("zeroPolicy", check, envir = .spdepOptions) - res + invisible(res) } get.ZeroPolicyOption <- function() { @@ -76,7 +88,7 @@ set.mcOption <- function(value) { } else { assign("mc", value, envir = .spdepOptions) } - res + invisible(res) } get.mcOption <- function() { @@ -93,7 +105,7 @@ set.coresOption <- function(value) { stopifnot(!is.na(value)) assign("cores", value, envir = .spdepOptions) } - res + invisible(res) } get.coresOption <- function() { diff --git a/R/subset.nb.R b/R/subset.nb.R index 6e7b1da3..9bb3963c 100644 --- a/R/subset.nb.R +++ b/R/subset.nb.R @@ -6,7 +6,11 @@ subset.nb <- function(x, subset, ...) { if (!inherits(x, "nb")) stop("not a neighbours list") if (!is.logical(subset)) stop("subset not a logical vector") n <- length(x) - input_nc <- n.comp.nb(x)$nc + input_nc <- attr(x, "ncomp")$nc + if (is.null(input_nc) && get.SubgraphOption() && + get.SubgraphCeiling() > (length(x) + sum(card(x)))) { + input_nc <- n.comp.nb(x)$nc + } if (n != length(subset)) stop("neighours list and subset vector different lengths") old.ids <- 1:n @@ -31,11 +35,17 @@ subset.nb <- function(x, subset, ...) { } attr(z, "region.id") <- reg.id for (i in 1:length(xattrs)) { - if (xattrs[i] != "region.id") + if (xattrs[i] != "region.id" && xattrs[i] != "ncomp") attr(z, xattrs[i]) <- attr(x, xattrs[i]) } z <- sym.attr.nb(z) - if (input_nc < n.comp.nb(z)$nc) warning("subsetting caused increase in subgraph count") + NE <- length(z) + sum(card(z)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(z) + attr(z, "ncomp") <- ncomp + if (!is.null(input_nc) && (input_nc < ncomp$nc)) + warning("subsetting caused increase in subgraph count") + } z } diff --git a/R/summary.nb.R b/R/summary.nb.R index 92511cd0..0600046f 100644 --- a/R/summary.nb.R +++ b/R/summary.nb.R @@ -53,17 +53,25 @@ print.nb <- function(x, ...) { n.nb <- length(nb) regids <- attr(nb, "region.id") if(is.null(regids)) regids <- as.character(1:n.nb) + s.c.nb <- sum(c.nb) cat("Neighbour list object:\n") cat("Number of regions:", n.nb, "\n") - cat("Number of nonzero links:", sum(c.nb), "\n") + cat("Number of nonzero links:", s.c.nb, "\n") cat("Percentage nonzero weights:", (100*sum(c.nb))/(n.nb^2), "\n") cat("Average number of links:", mean(c.nb), "\n") if(any(c.nb == 0)) cat(length(c.nb[c.nb == 0]), " region", ifelse(length(c.nb[c.nb == 0]) < 2L, "", "s"), " with no links:\n", paste(strwrap(paste(regids[which(c.nb == 0)], collapse=" ")), collapse="\n"), "\n", sep="") - comp <- n.comp.nb(x) - if (comp$nc > 1) cat(comp$nc, " disjoint connected subgraphs\n", sep="") + nc <- 0 + if (!is.null(attr(x, "ncomp"))) { + nc <- attr(x, "ncomp")$nc + } else { + if (get.SubgraphOption() && get.SubgraphCeiling() > s.c.nb+n.nb) { + nc <- n.comp.nb(x)$nc + } + } + if (nc > 1) cat(nc, " disjoint connected subgraphs\n", sep="") res <- is.symmetric.nb(nb, verbose=FALSE) if (!res) cat("Non-symmetric neighbours list\n") invisible(x) diff --git a/R/tolerance.nb.R b/R/tolerance.nb.R index a5efeb9f..df52c8f7 100644 --- a/R/tolerance.nb.R +++ b/R/tolerance.nb.R @@ -107,10 +107,12 @@ mat2nb <- function(x, row.names=NULL) { attr(neighbours, "call") <- NA attr(neighbours, "sym") <- is.symmetric.nb(neighbours, verbose=FALSE, force=TRUE) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(neighbours)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") - } + NE <- length(neighbours) + sum(card(neighbours)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(neighbours) + attr(neighbours, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") + } neighbours } diff --git a/R/tri2nb.R b/R/tri2nb.R index 2bc69376..4c688e72 100644 --- a/R/tri2nb.R +++ b/R/tri2nb.R @@ -51,9 +51,11 @@ tri2nb <- function(coords, row.names = NULL) { attr(nb, "tri") <- TRUE attr(nb, "call") <- match.call() nb <- sym.attr.nb(nb) - if (get.SubgraphOption()) { - nsg <- n.comp.nb(nb)$nc - if (nsg > 1) warning("neighbour object has ", nsg, " sub-graphs") + NE <- n + sum(card(nb)) + if (get.SubgraphOption() && get.SubgraphCeiling() > NE) { + ncomp <- n.comp.nb(nb) + attr(nb, "ncomp") <- ncomp + if (ncomp$nc > 1) warning("neighbour object has ", ncomp$nc, " sub-graphs") } nb } diff --git a/inst/tinytest/test_subgraph_warning.R b/inst/tinytest/test_subgraph_warning.R index cd296171..bdce2837 100644 --- a/inst/tinytest/test_subgraph_warning.R +++ b/inst/tinytest/test_subgraph_warning.R @@ -1,9 +1,10 @@ library(spdep) library(sf) -columbus <- st_read(system.file("shapes/columbus.shp", package="spData")[1], quiet=TRUE) +columbus <- st_read(system.file("shapes/columbus.gpkg", package="spData")[1], quiet=TRUE) col_geoms <- st_geometry(columbus) col_geoms[21] <- st_buffer(col_geoms[21], dist=-0.05) st_geometry(columbus) <- col_geoms +set.SubgraphOption(FALSE) expect_false(get.SubgraphOption()) expect_silent(nb <- poly2nb(columbus)) set.SubgraphOption(TRUE) diff --git a/man/compon.Rd b/man/compon.Rd index f2306191..fb6b5913 100644 --- a/man/compon.Rd +++ b/man/compon.Rd @@ -8,13 +8,12 @@ \code{n.comp.nb()} finds the number of disjoint connected subgraphs in the graph depicted by \code{nb.obj} - a spatial neighbours list object. } \usage{ -n.comp.nb(nb.obj, igraph=FALSE) +n.comp.nb(nb.obj) } \arguments{ \item{nb.obj}{a neighbours list object of class \code{nb}} - \item{igraph}{default \code{FALSE}, if \code{TRUE} use \code{igraph::components} after converting the neighbour object to a sparse adjacency matrix then a graph} } -\details{If \code{igraph=TRUE} and \code{attr(nb.obj, "sym")} is \code{FALSE}, the components of the directed graph will be found by a simple breadth-first search; if \code{igraph=FALSE} and \code{attr(nb.obj, "sym")} is \code{FALSE}, the object will be made symmetric (which may be time-consuming with large numbers of neighbours) and the components found by depth-first search. If \code{igraph=TRUE} or \code{FALSE} and \code{attr(nb.obj, "sym")} is \code{TRUE}, the components of the directed graph will be found by depth-first search.} +\details{If \code{attr(nb.obj, "sym")} is \code{FALSE} and \code{igraph::components} is available, the components of the directed graph will be found by a simple breadth-first search; if \code{igraph::components} is not available, the object will be made symmetric (which may be time-consuming with large numbers of neighbours) and the components found by depth-first search. If \code{attr(nb.obj, "sym")} is \code{TRUE}, the components of the directed graph will be found by depth-first search. The time complexity of algorithms used in native code and through \code{igraph::components} is linear in the sum of the number of nodes and the number of edges in the graph, see \url{https://github.com/r-spatial/spdep/issues/160} for details; very dense neighbour objects will have large numbers of edges.} \value{ A list of: \item{nc}{number of disjoint connected subgraphs} @@ -48,18 +47,55 @@ if (run) { print(all.equal(c1$csize, c(table(res$comp.id)), check.attributes=FALSE)) } if (run) { -resi <- n.comp.nb(col2, igraph=TRUE) -print(resi$nc == res$nc) +W <- as(nb2listw(col2, style="W", zero.policy=TRUE), "CsparseMatrix") +g1W <- graph_from_adjacency_matrix(W, mode="directed", weighted="W") +c1W <- components(g1W, mode="weak") +print(all.equal(c1W$membership, res$comp.id, check.attributes=FALSE)) } +\donttest{ if (run) { -print(all.equal(resi$comp.id, res$comp.id)) +data(house, package="spData") +house <- sf::st_as_sf(house) +k6 <- knn2nb(knearneigh(house, k=6)) +is.symmetric.nb(k6) } if (run) { -W <- as(nb2listw(col2, style="W", zero.policy=TRUE), "CsparseMatrix") -g1W <- graph_from_adjacency_matrix(W, mode="directed", weighted="W") -c1W <- components(g1W) -print(all.equal(c1W$membership, res$comp.id, check.attributes=FALSE)) +print(k6) +} +if (run) { +length(k6) + sum(card(k6)) +} +if (run) { +# no pre-computed graph components +str(attr(k6, "ncomp")) +} +if (run) { +# raising the subgraph compute ceiling to above |N|+|E| computes and stores the +# object in the neighbour object +set.SubgraphCeiling(180000L) +k6 <- knn2nb(knearneigh(house, k=6)) +str(attr(k6, "ncomp")) +} +if (run) { +print(k6) +} +if (run) { +system.time(udir <- n.comp.nb(make.sym.nb(k6))) } +if (run) { +system.time(dir <- n.comp.nb(k6)) } +if (run) { +udir$nc +} +if (run) { +dir$nc +} +if (run) { +all.equal(dir, udir) +} +} +} + \keyword{spatial} diff --git a/man/set.spChkOption.Rd b/man/set.spChkOption.Rd index 8de750ee..ea9c9711 100644 --- a/man/set.spChkOption.Rd +++ b/man/set.spChkOption.Rd @@ -7,6 +7,8 @@ \alias{get.VerboseOption} \alias{set.SubgraphOption} \alias{get.SubgraphOption} +\alias{set.SubgraphCeiling} +\alias{get.SubgraphCeiling} \alias{set.ZeroPolicyOption} \alias{get.ZeroPolicyOption} \alias{set.listw_is_CsparseMatrix_Option} @@ -27,12 +29,15 @@ set.ZeroPolicyOption(check) get.ZeroPolicyOption() set.SubgraphOption(check) get.SubgraphOption() +set.SubgraphCeiling(value) +get.SubgraphCeiling() set.listw_is_CsparseMatrix_Option(check) get.listw_is_CsparseMatrix_Option() } %- maybe also `usage' for other objects documented here. \arguments{ \item{check}{a logical value, TRUE or FALSE} + \item{value}{an integer value, initialised as 100000L, the sum of the numbers of nodes and edges in the neighbour graph} \item{x}{a vector the same length, or a two-dimensional array, or data frame with the same number of rows as the neighbours list in listw} \item{listw}{a \code{listw} object or \code{nb} object inheriting from "nb"} \item{var}{a character string or integer value for the column to be selected}