diff --git a/R/adjacency.R b/R/adjacency.R index 65b4eb21411..10497e4f3ff 100644 --- a/R/adjacency.R +++ b/R/adjacency.R @@ -494,8 +494,9 @@ graph.adjacency.sparse <- function( } vc <- nrow(adjmatrix) - # Exit early for empty graphs - if (vc == 1 || Matrix::nnzero(adjmatrix) == 0) { + # Exit early for empty graphs. Use na.counted = TRUE so that NA entries + # (which are stored explicitly) do not cause nnzero() to return NA. + if (vc == 1 || Matrix::nnzero(adjmatrix, na.counted = TRUE) == 0) { return(make_empty_graph(n = vc, directed = (mode == "directed"))) } diff --git a/R/utils-assert-args.R b/R/utils-assert-args.R index cfb2ddf3025..c80e7cb9cfd 100644 --- a/R/utils-assert-args.R +++ b/R/utils-assert-args.R @@ -66,9 +66,17 @@ igraph_match_arg <- function( #' @importFrom rlang caller_env ensure_no_na <- function(x, what, mode = "", call = caller_env()) { if (mode == "upper") { - x <- x[upper.tri(x)] + if (inherits(x, "sparseMatrix")) { + x <- Matrix::triu(x)@x + } else { + x <- x[upper.tri(x)] + } } else if (mode == "lower") { - x <- x[lower.tri(x)] + if (inherits(x, "sparseMatrix")) { + x <- Matrix::tril(x)@x + } else { + x <- x[lower.tri(x)] + } } if (anyNA(x)) { cli::cli_abort( diff --git a/tests/testthat/test-adjacency.R b/tests/testthat/test-adjacency.R index c4f2669202b..b43e54c3450 100644 --- a/tests/testthat/test-adjacency.R +++ b/tests/testthat/test-adjacency.R @@ -879,3 +879,37 @@ test_that("graph_from_adjacency Na check for upper/lower", { ) ) }) + +test_that("graph_from_adjacency NA check for upper/lower with sparse matrices", { + # Sparse matrix with NA only in upper triangle: mode="upper" should error, + # mode="lower" should succeed + sp <- Matrix::sparseMatrix( + i = c(1, 2, 1), + j = c(2, 1, 1), + x = c(NA_real_, 1, 1), + dims = c(3, 3) + ) + expect_error( + graph_from_adjacency_matrix(sp, mode = "upper", weighted = TRUE), + "contains NAs" + ) + expect_no_error( + graph_from_adjacency_matrix(sp, mode = "lower", weighted = TRUE) + ) + + # Sparse matrix with NA only in lower triangle: mode="lower" should error, + # mode="upper" should succeed + sp2 <- Matrix::sparseMatrix( + i = c(2, 1, 1), + j = c(1, 2, 1), + x = c(NA_real_, 1, 1), + dims = c(3, 3) + ) + expect_error( + graph_from_adjacency_matrix(sp2, mode = "lower", weighted = TRUE), + "contains NAs" + ) + expect_no_error( + graph_from_adjacency_matrix(sp2, mode = "upper", weighted = TRUE) + ) +})