Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion R/adjacency.R
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ graph.adjacency.sparse <- function(
res <- make_empty_graph(n = vc, directed = (mode == "directed"))
weight <- list(el[, 3])
names(weight) <- weighted
res <- add_edges(res, edges = t(as.matrix(el[, 1:2])), attr = weight)
res <- add_edges(res, edges = c(t(as.matrix(el[, 1:2]))), attr = weight)
} else {
if (max(el[, 3]) == 1) {
edges <- as.vector(t(el[, 1:2]))
Expand Down
4 changes: 2 additions & 2 deletions R/conversion.R
Original file line number Diff line number Diff line change
Expand Up @@ -1748,7 +1748,7 @@ graph_from_data_frame <- function(d, directed = TRUE, vertices = NULL) {
}

# add the edges
g <- add_edges(g, edges, attr = attrs)
g <- add_edges(g, c(edges), attr = attrs)
g
}

Expand Down Expand Up @@ -1800,7 +1800,7 @@ graph_from_edgelist <- function(el, directed = TRUE) {
V(res)$name <- names
} else {
## normal edge list
res <- make_graph(t(el), directed = directed)
res <- make_graph(c(t(el)), directed = directed)
}
}

Expand Down
2 changes: 1 addition & 1 deletion R/incidence.R
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ graph_incidence_build <- function(
res <- make_empty_graph(n = num_rows + num_cols, directed = directed)
weight_attr <- list(el[, 3])
names(weight_attr) <- weighted
res <- add_edges(res, edges = t(el[, 1:2]), attr = weight_attr)
res <- add_edges(res, edges = c(t(el[, 1:2])), attr = weight_attr)
} else {
# Handle unweighted edges, replicating rows for multiple edges
el <- el[rep(seq_len(nrow(el)), times = el[, 3]), 1:2]
Expand Down
2 changes: 1 addition & 1 deletion R/indexing.R
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ expand.grid.unordered <- function(i, j, loops = FALSE, directed = FALSE) {
## Addition or update of an attribute (or both)
ids <- get_edge_ids(x, c(rbind(from, to)))
if (any(ids == 0)) {
x <- add_edges(x, rbind(from[ids == 0], to[ids == 0]))
x <- add_edges(x, c(rbind(from[ids == 0], to[ids == 0])))
}
if (!is.null(attr)) {
ids <- get_edge_ids(x, c(rbind(from, to)))
Expand Down
37 changes: 29 additions & 8 deletions R/interface.R
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ add.edges <- function(graph, edges, ..., attr = list()) {
#' their values for the original edges of the graph are set to `NA`.
#'
#' @param graph The input graph
#' @param edges The edges to add, a vertex sequence with even number
#' of vertices.
#' @param edges The edges to add. Either a two-column matrix or data frame, each
#' row giving the two endpoints of an edge, or a vertex sequence with an even
#' number of vertices, interpreted pairwise (the first and second vertices
#' form the first edge, the third and fourth the second edge, etc.).
#' @param ... Additional arguments, they must be named,
#' and they will be added as edge attributes, for the newly added
#' edges. See also details below.
Expand Down Expand Up @@ -149,6 +151,10 @@ add_edges <- function(graph, edges, ..., attr = list()) {
cli::cli_abort("All attributes must be named.")
}

if (is.data.frame(edges) || inherits(edges, "matrix")) {
edges <- el_to_vec(edges, arg = "edges", fn = "add_edges")
}

edges.orig <- ecount(graph)
on.exit(.Call(Rx_igraph_finalizer))
graph <- .Call(
Expand Down Expand Up @@ -245,7 +251,8 @@ add_vertices <- function(graph, nv, ..., attr = list()) {
#' @param edges The edges to remove, specified as an edge sequence. Typically
#' this is either a numeric vector containing edge IDs, or a character vector
#' containing the IDs or names of the source and target vertices, separated by
#' `|`
#' `|`. A two-column matrix or data frame is also accepted, each row giving the
#' two endpoints of an edge to remove.
#' @return The graph, with the edges removed.
#'
#' @family functions for manipulating graph structure
Expand All @@ -264,6 +271,10 @@ add_vertices <- function(graph, nv, ..., attr = list()) {
#' g <- delete_edges(g, get_edge_ids(g, c(1, 5, 4, 5)))
#' g
delete_edges <- function(graph, edges) {
ensure_igraph(graph)
if (is.data.frame(edges) || inherits(edges, "matrix")) {
edges <- get_edge_ids(graph, edges, error = TRUE)
}
delete_edges_impl(
graph = graph,
edges = edges
Expand Down Expand Up @@ -455,7 +466,12 @@ get.edges <- function(graph, es) {
ends(graph, es, names = FALSE)
}

el_to_vec <- function(x, call = rlang::caller_env()) {
el_to_vec <- function(
x,
arg = "vp",
fn = "get_edge_ids",
call = rlang::caller_env()
) {
if (is.data.frame(x)) {
if (typeof(x[[1]]) == typeof(x[[2]])) {
c(rbind(x[[1]], x[[2]]))
Expand All @@ -471,26 +487,31 @@ el_to_vec <- function(x, call = rlang::caller_env()) {
if (nrow == 2 && ncol == 2) {
lifecycle::deprecate_stop(
"2.1.5",
"get_edge_ids(vp = 'is not allowed to be a 2 times 2 matrix')"
paste0(fn, "(", arg, " = 'is not allowed to be a 2 times 2 matrix')")
)
} else if (nrow == 2) {
lifecycle::deprecate_stop(
"2.1.5",
"get_edge_ids(vp = 'supplied as a matrix should be a n times 2 matrix, not 2 times n')",
paste0(
fn,
"(",
arg,
" = 'supplied as a matrix should be a n times 2 matrix, not 2 times n')"
),
details = "either transpose the matrix with t() or convert it to a data.frame with two columns."
)
} else if (ncol == 2) {
c(t(x))
} else {
cli::cli_abort(
"{.args vp} was supplied as a {dimx[1]} times {dimx[2]} matrix. Only n times 2 matrices are allowed"
"{.args {arg}} was supplied as a {dimx[1]} times {dimx[2]} matrix. Only n times 2 matrices are allowed"
)
}
} else if (is.vector(x)) {
x
} else {
cli::cli_abort(
"Only two-column data.frames and matrices, and vectors are allowed for {.args vp}",
"Only two-column data.frames and matrices, and vectors are allowed for {.args {arg}}",
call = call
)
}
Expand Down
7 changes: 6 additions & 1 deletion R/iterators.R
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,9 @@ unsafe_create_es <- function(graph, idx, es = NULL) {
#' @param graph The graph.
#' @param P A list of vertices to select edges via pairs of vertices.
#' The first and second vertices select the first edge, the third
#' and fourth the second, etc.
#' and fourth the second, etc. Alternatively, a two-column matrix or
#' data frame can be given, each row defining the two endpoints of an
#' edge to select.
#' @param path A list of vertices, to select edges along a path.
#' Note that this only works reliable for simple graphs. If the graph
#' has multiple edges, one of them will be chosen arbitrarily to
Expand Down Expand Up @@ -361,6 +363,9 @@ E <- function(graph, P = NULL, path = NULL, directed = TRUE) {
res <- seq_len(ec)
res <- set_complete_iterator(res)
} else if (!is.null(P)) {
if (is.data.frame(P) || inherits(P, "matrix")) {
P <- el_to_vec(P, arg = "P", fn = "E")
}
on.exit(.Call(Rx_igraph_finalizer))
res <- .Call(
Rx_igraph_es_pairs,
Expand Down
7 changes: 6 additions & 1 deletion R/make.R
Original file line number Diff line number Diff line change
Expand Up @@ -1381,7 +1381,8 @@ with_graph_ <- function(...) {
#' from the first element to the second, the second edge from the third
#' to the fourth, etc. For a numeric vector, these are interpreted
#' as internal vertex IDs. For character vectors, they are interpreted
#' as vertex names.
#' as vertex names. Alternatively, a two-column matrix or data frame
#' can be given, each row defining the two endpoints of an edge.
#'
#' Alternatively, this can be a character scalar, the name of a
#' notable graph. See Notable graphs below. The name is case
Expand Down Expand Up @@ -1467,6 +1468,10 @@ make_graph <- function(
directed <- dir
}

if (is.data.frame(edges) || inherits(edges, "matrix")) {
edges <- el_to_vec(edges, arg = "edges", fn = "make_graph")
}

if (is.character(edges) && length(edges) == 1) {
if (!missing(n)) {
cli::cli_warn("{.arg n} is ignored for the {.str {edges}} graph.")
Expand Down
36 changes: 30 additions & 6 deletions R/operators.R
Original file line number Diff line number Diff line change
Expand Up @@ -898,11 +898,14 @@ compose <- function(g1, g2, byname = "auto") {
#' `edge()` (or `edges()`) are concatenated, and then passed to
#' [add_edges()]. They are interpreted as pairs of vertex IDs,
#' and an edge will added between each pair. Named arguments will be
#' used as edge attributes for the new edges.
#' used as edge attributes for the new edges. Alternatively, a single
#' two-column matrix or data frame of edge endpoints can be passed as the
#' only unnamed argument.
#'
#' When deleting edges via `-`, all arguments of `edge()` (or
#' `edges()`) are concatenated via `c()` and passed to
#' [delete_edges()].
#' [delete_edges()]. A single two-column matrix or data frame of edge
#' endpoints can also be passed as the only argument.
#'
#' @param ... See details below.
#' @return A special object that can be used with together with
Expand Down Expand Up @@ -1139,13 +1142,27 @@ path <- function(...) {
## Adding edges, possibly with attributes
## Non-named arguments define the edges
if (is.null(names(e2))) {
toadd <- unlist(e2, recursive = FALSE)
unnamed <- e2
attr <- list()
} else {
toadd <- unlist(e2[!nzchar(names(e2))])
unnamed <- e2[!nzchar(names(e2))]
attr <- e2[nzchar(names(e2))]
}
res <- add_edges(e1, as_igraph_vs(e1, toadd), attr = attr)
if (
length(unnamed) == 1 &&
(is.data.frame(unnamed[[1]]) || inherits(unnamed[[1]], "matrix"))
) {
## A single two-column matrix or data frame of edge endpoints;
## let add_edges() normalize it via el_to_vec().
res <- add_edges(e1, unnamed[[1]], attr = attr)
} else {
if (is.null(names(e2))) {
toadd <- unlist(unnamed, recursive = FALSE)
} else {
toadd <- unlist(unnamed)
}
res <- add_edges(e1, as_igraph_vs(e1, toadd), attr = attr)
}
} else if (inherits(e2, "igraph.vertex")) {
## Adding vertices, possibly with attributes
## If there is a single unnamed argument, that contains the vertex names
Expand Down Expand Up @@ -1250,7 +1267,14 @@ path <- function(...) {
} else if (inherits(e2, "igraph.vertex")) {
res <- delete_vertices(e1, unlist(e2, recursive = FALSE))
} else if (inherits(e2, "igraph.edge")) {
res <- delete_edges(e1, unlist(e2, recursive = FALSE))
if (
length(e2) == 1 && (is.data.frame(e2[[1]]) || inherits(e2[[1]], "matrix"))
) {
todel <- e2[[1]]
} else {
todel <- unlist(e2, recursive = FALSE)
}
res <- delete_edges(e1, todel)
} else if (inherits(e2, "igraph.path")) {
todel <- unlist(e2, recursive = FALSE)
lt <- length(todel)
Expand Down
2 changes: 1 addition & 1 deletion R/structural-properties.R
Original file line number Diff line number Diff line change
Expand Up @@ -1182,7 +1182,7 @@ degree_distribution <- function(graph, cumulative = FALSE, ...) {
#' 9, 10, 4
#' )
#' )
#' g2 <- add_edges(make_empty_graph(10), t(el[, 1:2]), weight = el[, 3])
#' g2 <- add_edges(make_empty_graph(10), el[, 1:2], weight = el[, 3])
#' distances(g2, mode = "out")
#'
distances <- function(
Expand Down
4 changes: 3 additions & 1 deletion man/E.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions man/add.edges.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions man/add_edges.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/delete.edges.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/delete_edges.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/distances.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions man/edge.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/graph.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/graph.famous.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/make_graph.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/testthat/test-conversion.R
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ test_that("as_adj_list works when return.vs.es is FALSE", {
test_that("as_edgelist works", {
g <- sample_gnp(100, 3 / 100)
el <- as_edgelist(g)
g2 <- make_graph(t(el), n = vcount(g), dir = FALSE)
g2 <- make_graph(el, n = vcount(g), dir = FALSE)
expect_isomorphic(g, g2)
})

Expand Down
Loading
Loading