diff --git a/DESCRIPTION b/DESCRIPTION index 2b13596..d22937e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -18,7 +18,7 @@ BugReports: https://github.com/thomasp85/tidygraph/issues Imports: cli, dplyr (>= 0.8.5), - igraph (>= 1.5.0), + igraph (>= 2.0.0), lifecycle, magrittr, pillar, @@ -45,5 +45,5 @@ LinkingTo: cpp11 Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.1 Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index f67fd2f..91c712c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -73,6 +73,8 @@ S3method(sample_n,tbl_graph) S3method(select,morphed_tbl_graph) S3method(select,tbl_graph) S3method(semi_join,tbl_graph) +S3method(set_graph_data,grouped_tbl_graph) +S3method(set_graph_data,tbl_graph) S3method(slice,morphed_tbl_graph) S3method(slice,tbl_graph) S3method(slice_head,morphed_tbl_graph) @@ -461,6 +463,7 @@ importFrom(igraph,add_edges) importFrom(igraph,add_vertices) importFrom(igraph,adjacent_vertices) importFrom(igraph,alpha_centrality) +importFrom(igraph,arpack_defaults) importFrom(igraph,articulation_points) importFrom(igraph,as.igraph) importFrom(igraph,as_adjacency_matrix) @@ -537,7 +540,6 @@ importFrom(igraph,has_eulerian_cycle) importFrom(igraph,has_eulerian_path) importFrom(igraph,hub_score) importFrom(igraph,induced_subgraph) -importFrom(igraph,is.directed) importFrom(igraph,is_bipartite) importFrom(igraph,is_chordal) importFrom(igraph,is_connected) diff --git a/NEWS.md b/NEWS.md index 59e22ef..129091c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # tidygraph (development version) * Fix a bug in `tbl_graph()` when edge `to` and `from` where encoded as factors +* Secure compitability with igraph 2.0.0 # tidygraph 1.3.0 diff --git a/R/arrange.R b/R/arrange.R index 4d2994c..226254c 100644 --- a/R/arrange.R +++ b/R/arrange.R @@ -24,11 +24,11 @@ arrange.morphed_tbl_graph <- function(.data, ...) { #' @export dplyr::arrange -#' @importFrom igraph is.directed as_data_frame +#' @importFrom igraph is_directed as_data_frame permute_edges <- function(graph, order) { graph_mod <- as_data_frame(graph, what = 'both') graph_mod$edges <- graph_mod$edges[order, ] - as_tbl_graph(graph_mod, directed = is.directed(graph)) + as_tbl_graph(graph_mod, directed = is_directed(graph)) } #' @importFrom igraph permute permute_nodes <- function(graph, order) { diff --git a/R/centrality.R b/R/centrality.R index ff0e5e8..e96cf24 100644 --- a/R/centrality.R +++ b/R/centrality.R @@ -61,9 +61,9 @@ centrality_alpha <- function(weights = NULL, alpha = 1, exo = 1, tol = 1e-7, loo alpha_centrality(graph = graph, nodes = focus_ind(graph, 'nodes'), alpha = alpha, exo = exo, weights = weights, tol = tol, loops = loops) } #' @describeIn centrality Wrapper for [igraph::authority_score()] -#' @importFrom igraph authority_score +#' @importFrom igraph authority_score arpack_defaults #' @export -centrality_authority <- function(weights = NULL, scale = TRUE, options = igraph::arpack_defaults) { +centrality_authority <- function(weights = NULL, scale = TRUE, options = arpack_defaults()) { expect_nodes() weights <- enquo(weights) weights <- eval_tidy(weights, .E()) %||% NA @@ -104,9 +104,9 @@ centrality_closeness <- function(weights = NULL, mode = 'out', normalized = FALS closeness(graph = graph, vids = focus_ind(graph, 'nodes'), mode = mode, cutoff = cutoff, weights = weights, normalized = normalized) } #' @describeIn centrality Wrapper for [igraph::eigen_centrality()] -#' @importFrom igraph eigen_centrality +#' @importFrom igraph eigen_centrality arpack_defaults #' @export -centrality_eigen <- function(weights = NULL, directed = FALSE, scale = TRUE, options = igraph::arpack_defaults) { +centrality_eigen <- function(weights = NULL, directed = FALSE, scale = TRUE, options = arpack_defaults()) { expect_nodes() weights <- enquo(weights) weights <- eval_tidy(weights, .E()) %||% NA @@ -114,9 +114,9 @@ centrality_eigen <- function(weights = NULL, directed = FALSE, scale = TRUE, opt eigen_centrality(graph = graph, directed = directed, scale = scale, weights = weights, options = options)$vector[focus_ind(graph, 'nodes')] } #' @describeIn centrality Wrapper for [igraph::hub_score()] -#' @importFrom igraph hub_score +#' @importFrom igraph hub_score arpack_defaults #' @export -centrality_hub <- function(weights = NULL, scale = TRUE, options = igraph::arpack_defaults) { +centrality_hub <- function(weights = NULL, scale = TRUE, options = arpack_defaults()) { expect_nodes() weights <- enquo(weights) weights <- eval_tidy(weights, .E()) %||% NA @@ -151,7 +151,7 @@ centrality_degree <- function(weights = NULL, mode = 'out', loops = TRUE, normal expect_nodes() graph <- .G() weights <- enquo(weights) - weights <- eval_tidy(weights, .E()) %||% NA + weights <- eval_tidy(weights, .E()) if (is.null(weights)) { degree(graph = graph, v = focus_ind(graph, 'nodes'), mode = mode, loops = loops, normalized = normalized) } else { @@ -187,11 +187,12 @@ centrality_harmonic <- function(weights = NULL, mode = 'out', normalized = FALSE #' @param aggregation The aggregation type to use on the indirect relations to be used in `netrankr::aggregate_positions` #' @param ... Arguments to pass on to `netrankr::indirect_relations` #' @export +#' @importFrom igraph is_directed centrality_manual <- function(relation = 'dist_sp', aggregation = 'sum', ...) { expect_netrankr() expect_nodes() graph <- .G() - if (is.directed(graph)) { + if (is_directed(graph)) { cli::cli_abort("Centrality measures based on the {.pkg netrankr} package only works on undirected networks") } rel <- netrankr::indirect_relations(graph, type = relation, ...) diff --git a/R/graph_measures.R b/R/graph_measures.R index aaf50c3..837bccb 100644 --- a/R/graph_measures.R +++ b/R/graph_measures.R @@ -39,9 +39,9 @@ graph_assortativity <- function(attr, in_attr = NULL, directed = TRUE) { if (is.numeric(attr)) { in_attr <- enquo(in_attr) in_attr <- eval_tidy(in_attr, .N(focused = FALSE)) - assortativity(graph, attr, in_attr, directed) + assortativity(graph, values = attr, values.in = in_attr, directed = directed) } else { - assortativity_nominal(graph, as.factor(attr), directed) + assortativity_nominal(graph, types = as.factor(attr), directed = directed) } } #' @describeIn graph_measures Calculate the number of automorphisms of the graph. Wraps [igraph::count_automorphisms()] diff --git a/R/group.R b/R/group.R index c4ec5d3..02b7718 100644 --- a/R/group.R +++ b/R/group.R @@ -115,9 +115,9 @@ group_label_prop <- function(weights = NULL, label = NULL, fixed = NULL) { desc_enumeration(group) } #' @describeIn group_graph Group nodes based on the leading eigenvector of the modularity matrix using [igraph::cluster_leading_eigen()] -#' @importFrom igraph membership cluster_leading_eigen cut_at +#' @importFrom igraph membership cluster_leading_eigen cut_at arpack_defaults #' @export -group_leading_eigen <- function(weights = NULL, steps = -1, label = NULL, options = igraph::arpack_defaults, n_groups = NULL) { +group_leading_eigen <- function(weights = NULL, steps = -1, label = NULL, options = arpack_defaults(), n_groups = NULL) { expect_nodes() weights <- enquo(weights) weights <- eval_tidy(weights, .E()) %||% NA diff --git a/R/node.R b/R/node.R index 2f7fefc..08fb4c3 100644 --- a/R/node.R +++ b/R/node.R @@ -28,13 +28,13 @@ node_is_cut <- function() { focus_ind(graph, 'nodes') %in% articulation_points(graph) } #' @describeIn node_types is the node a root in a tree -#' @importFrom igraph degree is.directed +#' @importFrom igraph degree is_directed #' @export node_is_root <- function() { expect_nodes() graph <- .G() node_inds <- focus_ind(graph, 'nodes') - if ((!is_tree(graph) && !is_forest(graph)) || !is.directed(graph)) { + if ((!is_tree(graph) && !is_forest(graph)) || !is_directed(graph)) { return(rep(FALSE, length(node_inds))) } deg_in <- degree(graph, mode = 'in') == 0 @@ -43,7 +43,7 @@ node_is_root <- function() { root[node_inds] } #' @describeIn node_types is the node a leaf in a tree -#' @importFrom igraph degree is.directed +#' @importFrom igraph degree is_directed #' @export node_is_leaf <- function() { expect_nodes() @@ -52,7 +52,7 @@ node_is_leaf <- function() { if ((!is_tree(graph) && !is_forest(graph))) { return(rep(FALSE, length(node_inds))) } - if (is.directed(graph)) { + if (is_directed(graph)) { deg_in <- degree(graph, mode = 'in') == 0 deg_out <- degree(graph, mode = 'out') == 0 leaf <- if (sum(deg_out) > sum(deg_in)) deg_out else deg_in diff --git a/R/random_walk.R b/R/random_walk.R index fed104f..a024ea8 100644 --- a/R/random_walk.R +++ b/R/random_walk.R @@ -50,15 +50,15 @@ random_walk_rank <- function(n, root = NULL, mode = "out", weights = NULL) { if (!quo_is_null(weights)) { cli::cli_warn('{.arg weights} is ignored when doing a random walk on nodes') } - walk <- as.integer(random_walk(graph, root, n, mode)) + walk <- as.integer(random_walk(graph, root, n, mode = mode)) len_out <- gorder(graph) } else { weights <- eval_tidy(weights, .E(focused = FALSE)) %||% NA - walk <- as.integer(random_edge_walk(graph, root, n, weights, mode)) + walk <- as.integer(random_edge_walk(graph, root, n, weights, mode = mode)) len_out <- gsize(graph) } res <- rep(list(integer()), len_out) - ord <- split(seq_len(n), walk) + ord <- split(seq_along(walk), walk) res[as.integer(names(ord))] <- ord res[focus_ind(graph, active(graph))] } diff --git a/R/reroute.R b/R/reroute.R index 7bddfe8..77f8e7f 100644 --- a/R/reroute.R +++ b/R/reroute.R @@ -32,7 +32,7 @@ reroute <- function(.data, from = NULL, to = NULL, subset = NULL) { } #' @export #' @importFrom rlang enquo eval_tidy -#' @importFrom igraph is.directed +#' @importFrom igraph is_directed reroute.tbl_graph <- function(.data, from = NULL, to = NULL, subset = NULL) { .register_graph_context(.data) expect_edges() @@ -54,7 +54,7 @@ reroute.tbl_graph <- function(.data, from = NULL, to = NULL, subset = NULL) { .data <- tbl_graph( nodes = as_tibble(.data, active = 'nodes'), edges = edges, - directed = is.directed(.data) + directed = is_directed(.data) ) %gr_attr% .data active(.data) <- 'edges' .data diff --git a/R/tbl_graph.R b/R/tbl_graph.R index 3976cf9..608d576 100644 --- a/R/tbl_graph.R +++ b/R/tbl_graph.R @@ -199,6 +199,7 @@ as_tbl_graph.tbl_graph <- function(x, ...) { set_graph_data <- function(x, value, active) { UseMethod('set_graph_data') } +#' @export set_graph_data.tbl_graph <- function(x, value, active = NULL) { if (is.null(active)) active <- active(x) switch( @@ -208,6 +209,7 @@ set_graph_data.tbl_graph <- function(x, value, active = NULL) { cli::cli_abort('Unknown active element: {.val {active}}. Only nodes and edges supported') ) } +#' @export set_graph_data.grouped_tbl_graph <- function(x, value, active = NULL) { x <- NextMethod() apply_groups(x, value) diff --git a/man/centrality.Rd b/man/centrality.Rd index a1c51be..92dffe9 100644 --- a/man/centrality.Rd +++ b/man/centrality.Rd @@ -44,11 +44,7 @@ centrality_alpha( loops = FALSE ) -centrality_authority( - weights = NULL, - scale = TRUE, - options = igraph::arpack_defaults -) +centrality_authority(weights = NULL, scale = TRUE, options = arpack_defaults()) centrality_betweenness( weights = NULL, @@ -70,10 +66,10 @@ centrality_eigen( weights = NULL, directed = FALSE, scale = TRUE, - options = igraph::arpack_defaults + options = arpack_defaults() ) -centrality_hub(weights = NULL, scale = TRUE, options = igraph::arpack_defaults) +centrality_hub(weights = NULL, scale = TRUE, options = arpack_defaults()) centrality_pagerank( weights = NULL, diff --git a/man/focus.Rd b/man/focus.Rd index b78284f..ae9efd1 100644 --- a/man/focus.Rd +++ b/man/focus.Rd @@ -29,10 +29,11 @@ unfocus(.data, ...) lazy data frame (e.g. from dbplyr or dtplyr). See \emph{Methods}, below, for more details.} -\item{...}{<\code{\link[dplyr:dplyr_data_masking]{data-masking}}> Expressions that return a -logical value, and are defined in terms of the variables in \code{.data}. -If multiple expressions are included, they are combined with the \code{&} operator. -Only rows for which all conditions evaluate to \code{TRUE} are kept.} +\item{...}{<\code{\link[rlang:args_data_masking]{data-masking}}> Expressions that +return a logical value, and are defined in terms of the variables in +\code{.data}. If multiple expressions are included, they are combined with the +\code{&} operator. Only rows for which all conditions evaluate to \code{TRUE} are +kept.} } \value{ A graph with focus applied diff --git a/man/group_graph.Rd b/man/group_graph.Rd index 7cbd6ac..67cac23 100644 --- a/man/group_graph.Rd +++ b/man/group_graph.Rd @@ -32,7 +32,7 @@ group_leading_eigen( weights = NULL, steps = -1, label = NULL, - options = igraph::arpack_defaults, + options = arpack_defaults(), n_groups = NULL ) diff --git a/man/map_bfs.Rd b/man/map_bfs.Rd index 4aada9c..30fc165 100644 --- a/man/map_bfs.Rd +++ b/man/map_bfs.Rd @@ -80,7 +80,7 @@ create_tree(40, children = 3, directed = TRUE) \%>\% \seealso{ Other node map functions: \code{\link{map_bfs_back}()}, -\code{\link{map_dfs_back}()}, -\code{\link{map_dfs}()} +\code{\link{map_dfs}()}, +\code{\link{map_dfs_back}()} } \concept{node map functions} diff --git a/man/map_bfs_back.Rd b/man/map_bfs_back.Rd index 0857552..11da0fa 100644 --- a/man/map_bfs_back.Rd +++ b/man/map_bfs_back.Rd @@ -83,7 +83,7 @@ create_tree(40, children = 3, directed = TRUE) \%>\% \seealso{ Other node map functions: \code{\link{map_bfs}()}, -\code{\link{map_dfs_back}()}, -\code{\link{map_dfs}()} +\code{\link{map_dfs}()}, +\code{\link{map_dfs_back}()} } \concept{node map functions} diff --git a/man/map_dfs.Rd b/man/map_dfs.Rd index 0ddecca..df06e7c 100644 --- a/man/map_dfs.Rd +++ b/man/map_dfs.Rd @@ -76,8 +76,8 @@ create_tree(40, children = 3, directed = TRUE) \%>\% } \seealso{ Other node map functions: -\code{\link{map_bfs_back}()}, \code{\link{map_bfs}()}, +\code{\link{map_bfs_back}()}, \code{\link{map_dfs_back}()} } \concept{node map functions} diff --git a/man/map_dfs_back.Rd b/man/map_dfs_back.Rd index 9999fe2..5f243ca 100644 --- a/man/map_dfs_back.Rd +++ b/man/map_dfs_back.Rd @@ -79,8 +79,8 @@ create_tree(40, children = 3, directed = TRUE) \%>\% } \seealso{ Other node map functions: -\code{\link{map_bfs_back}()}, \code{\link{map_bfs}()}, +\code{\link{map_bfs_back}()}, \code{\link{map_dfs}()} } \concept{node map functions} diff --git a/tests/testthat/test-random-walk.R b/tests/testthat/test-random-walk.R index f2f36fb..3652bd5 100644 --- a/tests/testthat/test-random-walk.R +++ b/tests/testthat/test-random-walk.R @@ -1,7 +1,7 @@ test_that("random_walk_rank returns correct data", { set.seed(1) node_walk <- create_notable('zachary') |> - mutate(walk_rank = random_walk_rank(30, 5)) |> + mutate(walk_rank = random_walk_rank(29, 5)) |> pull(walk_rank) edge_walk <- create_notable('zachary') |> @@ -13,9 +13,9 @@ test_that("random_walk_rank returns correct data", { expect_length(edge_walk, 78) expect_type(node_walk, 'list') expect_type(edge_walk, 'list') - expect_equal(node_walk[[5]], c(1, 12)) - expect_equal(node_walk[[2]], integer()) + expect_equal(node_walk[[5]], c(1, 5, 7)) + expect_equal(node_walk[[3]], integer()) expect_equal(edge_walk[[1]], integer()) skip_on_cran() - expect_equal(edge_walk[[36]], 1:4) + expect_equal(edge_walk[[4]], c(1, 18)) })