Skip to content

graph

Build NetworkX graphs from flow frames and convert them back.

Build NetworkX graphs from flow frames.

A graph represents exactly one slice of the data: one time value and one category, unless you ask for an explicit aggregation. Every graph stores the slice it came from in G.graph, and every edge carries its amount in the "weight" attribute, which is the default weight name used by NetworkX algorithms.

Aggregate module-attribute

Aggregate: TypeAlias = Literal['sum', 'mean']

How to combine flows across slices: "sum" totals them; "mean" divides the total by the number of slices present, so a pair that is missing from a slice counts as zero for that slice.

build_graph

build_graph(
    flows: FlowFrame,
    *,
    time: int | Iterable[int] | None = None,
    category: Hashable | Iterable[Hashable] | None = None,
    aggregate: Aggregate | None = None,
    directed: bool = True,
    self_loops: bool = False,
    node_attrs: DataFrame | None = None,
) -> DiGraph[Any] | Graph[Any]

Build a weighted graph from one slice of a flow frame.

Parameters:

Name Type Description Default
flows FlowFrame

A flow frame, or any table with source, target and weight columns.

required
time int | Iterable[int] | None

Keep only flows with this time value, or with any of these values (for example range(2015, 2020)), before building.

None
category Hashable | Iterable[Hashable] | None

Keep only flows with this category value, or with any of these values, before building.

None
aggregate Aggregate | None

Required when the (filtered) flows contain more than one time or category value. "sum" totals the flows; "mean" averages them over the slices present. Duplicate rows for the same pair inside one slice are always summed.

None
directed bool

Return a networkx.DiGraph (default). If False, return a networkx.Graph in which both directions of a pair are summed.

True
self_loops bool

Keep flows whose source equals their target. Dropped by default.

False
node_attrs DataFrame | None

Optional table indexed by node label. Its columns become node attributes for the nodes present in the graph, for example netviz_tools.datasets.faostat.countries.

None

Returns:

Type Description
DiGraph or Graph

Edge amounts are stored under "weight". G.graph records time, category and unit where they are known (a list of values when several were aggregated), aggregate, n_slices when aggregating, and labels (a copy of flows.attrs["labels"]) when the flows carry display labels.

Raises:

Type Description
MixedSliceError

If the flows span several time or category values and aggregate is None.

MixedUnitError

If the flows have more than one unit.

ValueError

If a time or category value matches no flows. The message lists the available values.

SchemaError

If a required column is missing or weights are negative or missing.

Examples:

>>> import netviz_tools as nv
>>> flows = nv.datasets.faostat.load_sample()
>>> g = nv.build_graph(flows, time=2021, category="Wheat")
>>> g.graph["time"], g.graph["category"], g.graph["unit"]
(2021, 'Wheat', 't')
>>> g.graph["labels"]["source"]
'Exporter'

graphs_by

graphs_by(
    flows: FlowFrame,
    by: str | Sequence[str] = ("time", "category"),
    **kwargs: Any,
) -> dict[Hashable, DiGraph[Any] | Graph[Any]]

Build one graph per group of a flow frame.

Parameters:

Name Type Description Default
flows FlowFrame

A flow frame.

required
by str | Sequence[str]

Column or columns to group on. The default builds one graph per (time, category) slice.

('time', 'category')
**kwargs Any

Passed to build_graph. time= and category= filters are applied to the whole frame before grouping. If you group by "time" only and the flows contain several categories, pass aggregate= or category= here.

{}

Returns:

Type Description
dict

Keys are group values in sorted order: scalars when grouping on one column, tuples otherwise. Every graph carries flows.attrs["labels"] in G.graph["labels"] when present.

Examples:

>>> import netviz_tools as nv
>>> flows = nv.datasets.faostat.load_sample(years=range(2019, 2023))
>>> sorted(nv.graphs_by(flows, by="time", category="Wheat"))
[2019, 2020, 2021, 2022]

graph_to_flows

graph_to_flows(g: Graph[Any]) -> DataFrame

Convert a graph back into a flow table.

Scalar slice metadata stored by build_graph (time, category, unit) is added as constant columns, so a graph built from one slice converts back into a valid flow frame. G.graph["labels"], when present, is copied into df.attrs["labels"].

Parameters:

Name Type Description Default
g Graph[Any]

A graph whose edges carry "weight" (missing weights count as 1).

required

Returns:

Type Description
DataFrame

One row per edge with the columns of netviz_tools.FLOW_COLUMNS that are known, sorted by source and target.