Skip to content

Hierarchies

Two ways to describe a tree. A named hierarchy is reusable shorthand — declare geography = [region, country, city] once and reference it by name on either axis. An adjacency list is data already shaped as a tree: flat rows carrying an id and a parent_id, which the engine nests and rolls up bottom-up (org charts, bills-of-materials, category trees). Either way the engine builds the tree and the numbers; the grid just shows it.

A hierarchy name used in rows / columns expands to its ordered level list (fixed order, no recursion, duplicates dropped). It is a Dash-config convenience; the adapters take the expanded level list directly as rows.

from dash_tensor_grid import TensorGrid, build_grid
payload = build_grid(sales, {
"hierarchies": {"geography": ["region", "country", "city"]},
"rows": ["geography"], # -> region, country, city
"measures": {"revenue": "sum", "qty": "sum"},
"formats": {"revenue": "currency:USD"},
"grand_total": True,
})
TensorGrid(id="grid", row_data=payload["row_data"], column_defs=payload["column_defs"])

When the source is a parent-pointer table, nest it with the engine helper. Interior nodes roll up bottom-up from their descendants (measures); leaves keep their own values. orphans chooses whether a row with a missing parent becomes a root ('root', default) or is dropped.

from dash_tensor_grid import GridDataEngine, TensorGrid
# Each row: id + parent_id (+ its own measures on the leaves).
tree = GridDataEngine(rows).build_adjacency_tree(
"id", "parent_id", measures={"headcount": "sum", "budget": "sum"},
)
column_defs = [
{"accessorKey": "name", "header": "Org unit", "type": "string"},
{"accessorKey": "budget", "header": "Budget", "type": "number", "formatStr": "currency:USD:compact"},
]
TensorGrid(id="grid", row_data=tree, column_defs=column_defs, initial_state={"expanded": True})
  • Named hierarchies are fixed-order and non-recursive. A name that matches a hierarchies key expands to its levels; any other name passes through, so rows: [geography, segment] mixes freely. Duplicate columns are dropped (first occurrence wins).
  • build_adjacency_tree / buildAdjacencyTree roll interior nodes up with sum / mean / min / max / count per field; labelField copies a column onto each node as label; the output is JSON-safe and byte-identical between the engine and the core port.
  • Pair a deep hierarchy with the virtualized grid when the tree gets large, or an auto-group column to give the hierarchy its own dedicated column.