Set operations across two graph objects, regardless of their concrete
representation (igraph/tbl_graph, or a visNetwork
htmlwidget such as funviewR::plot_dependency_graph() returns).
Both graphs are normalized via as_database, combined with the
database_setops verbs (dplyr::intersect()/
dplyr::setdiff()/dplyr::union() on the cbe_database
class), and rebuilt into an igraph with database_to_igraph.
Usage
graph_intersect(x, y, directed = TRUE)
graph_subtract(x, y, directed = TRUE)
graph_union(x, y, directed = TRUE)Value
An igraph object. Call as_database on the
result to get the underlying node/edge tibbles.
Details
These stay dedicated functions rather than intersect.igraph()/
union.igraph()/setdiff.igraph() methods because igraph
already registers its own union.igraph() on the same generic –
S3 method tables are global, so defining one here would silently collide
with igraph's. Going through as_database first sidesteps that
entirely: dispatch happens on the cbe_database class this package
owns, not on igraph.
graph_intersect() keeps nodes/edges present in both x
and y, taking attribute values from x only. graph_subtract()
keeps nodes/edges present in x but not in y (edges are
additionally constrained to only reference surviving nodes, so the result
is always well-formed). graph_union() combines both graphs' nodes
and edges, coalescing attribute values so neither side's data is lost on
overlap – the same union-and-coalesce behavior as join_pipelines,
generalized to any graph type via as_database rather than
tbl_graph specifically.
All three are set operations – which nodes/edges exist where – not a
value-level comparison of attributes on nodes/edges that happen to match.
For that, run compare_df on the two as_database
results directly (or on the two graphs themselves).
Examples
g1 <- igraph::graph_from_data_frame(
data.frame(from = c("a", "b"), to = c("b", "c")),
vertices = data.frame(name = c("a", "b", "c"))
)
g2 <- igraph::graph_from_data_frame(
data.frame(from = "a", to = "b"),
vertices = data.frame(name = c("a", "b"))
)
graph_intersect(g1, g2)
#> IGRAPH fdba346 DN-- 2 1 --
#> + attr: name (v/c)
#> + edge from fdba346 (vertex names):
#> [1] a->b
graph_subtract(g1, g2)
#> IGRAPH f92ecfa DN-- 1 0 --
#> + attr: name (v/c)
#> + edges from f92ecfa (vertex names):
graph_union(g1, g2)
#> IGRAPH c7f5b7c DN-- 3 2 --
#> + attr: name (v/c)
#> + edges from c7f5b7c (vertex names):
#> [1] a->b b->c
