Consolidate a graph by contracting/removing intermediate nodes (nodes that occur exactly twice) and dropping loop, duplicate, and singleton edges (leading to dead ends). This simplifies the network topology while preserving connectivity.
consolidate_graph(
graph_df,
directed = FALSE,
drop.edges = c("loop", "duplicate", "single"),
contract = TRUE,
by = NULL,
keep.nodes = NULL,
...,
recursive = "full",
verbose = TRUE
)A data frame representing the consolidated graph with:
All columns from graph_df (aggregated if consolidation occurred),
excluding from, to, and optionally edge and FX, FY, TX, TY
(which are re-added if present in original)
from, to, edge - Node/edge IDs (updated after consolidation)
Coordinate columns (FX, FY, TX, TY) if present in original
Attribute "keep.edges" - Indices of original edges that were kept (before aggregation)
Attribute "group.id" - Integer mapping each kept edge to its row in the result (after aggregation)
A data frame representing a graph with columns:
from and to (node IDs), and optionally other columns to preserve.
If coordinate columns (FX, FY, TX, TY) are present, they will be
preserved and updated based on the consolidated node coordinates.
Logical (default: FALSE). Whether the graph is directed.
Character vector (default: c("loop", "duplicate", "single")). Types of edges to drop:
"loop" removes self-loops (edges where from == to),
"duplicate" removes duplicate edges (same from-to pair),
"single" removes edges leading to singleton nodes (nodes that occur only once).
Set to NULL to keep all edges.
Logical (default: TRUE). If TRUE, contracts the graph by removing
intermediate nodes (nodes that occur exactly twice) and merging connecting edges.
If FALSE, only drops edges as specified in drop.edges.
Link characteristics to preserve/not contract across, passed as a one-sided formula or character vector of column names. Typically this includes attributes like mode, type, or capacity to ensure that only edges with the same characteristics are contracted.
Numeric vector (optional). Node IDs to preserve during consolidation, even if they occur exactly twice. Also used to preserve nodes when dropping singleton edges.
Arguments passed to collap() for aggregation across contracted edges. The defaults are FUN = fmean for numeric columns and catFUN = fmode for categorical columns. Select columns using cols or use argument custom = list(fmean = cols1, fsum = cols2, fmode = cols3) to map different columns to specific aggregation functions. It is highly recommended to weight the aggregation (using w = ~ weight_col) by the length/cost of the edges.
One of "none"/FALSE (drop edges, contract, and aggregate once), "partial" (recursively drop edges and contract but only aggregate once), or "full"/TRUE (recursively drop edges, contract, and aggregate the graph
until no further consolidation is possible).
Logical (default: TRUE). Whether to print messages about dropped edges and consolidation progress.
This function consolidates/simplifies a graph by:
Dropping edges: Optionally removes self-loops, duplicate edges, and edges leading to singleton nodes (nodes that appear only once in the graph)
Contracting nodes: Removes intermediate nodes (nodes that occur exactly twice) by merging the two edges connected through them into a single longer edge
Aggregating attributes: When edges are merged, attributes/columns are aggregated
using collap(). The default aggregation is mean for numeric columns and mode for categorical columns.
Recursive consolidation: If recursive = TRUE, the function continues
consolidating until no more nodes can be dropped or contracted, ensuring complete consolidation
Consolidation is useful for simplifying network topology while preserving connectivity.
For example, if node B connects A->B and B->C, it will be removed and replaced with A->C.
With recursive = TRUE, long chains (A->B->C->D) are fully contracted to A->D in
a single call.
For undirected graphs, the algorithm also handles cases where a node appears twice as either origin or destination (circular cases).
If coordinate columns (FX, FY, TX, TY) are present in the input,
they are preserved and updated based on the consolidated node coordinates from the original graph.
create_undirected_graph simplify_network flownet-package
library(flownet)
library(sf)
# Convert segments to undirected graph
graph <- africa_segments |>
linestrings_from_graph() |>
linestrings_to_graph() |>
create_undirected_graph(FUN = "fsum")
# Get nodes to preserve (city/port locations)
nodes <- nodes_from_graph(graph, sf = TRUE)
nearest_nodes <- nodes$node[st_nearest_feature(africa_cities_ports, nodes)]
# Consolidate graph, preserving city nodes
graph_cons <- consolidate_graph(graph, keep = nearest_nodes, w = ~ passes)
# Consolidated graph has fewer edges
c(original = nrow(graph), consolidated = nrow(graph_cons))
Run the code above in your browser using DataLab