Skip to content

Build hierarchical visualizations

HierarchyPlotter builds a tree of subgroup counts and optional continuous-score aggregates. It returns data arrays; it does not render a chart itself.

Plotly is not a Model Auditor dependency.

Terminal window
python -m pip install plotly
from model_auditor.plotting import HierarchyPlotter
plotter = HierarchyPlotter()
plotter.set_data(data)
plotter.set_features(
[
"region",
"age_group",
"device_type",
]
)
plotter.set_score(
name="risk_score",
label="Risk score",
)
plotter.set_aggregator("median")
plot_data = plotter.compile(
container="All observations",
)

The root and every hierarchy node receive:

  • a display label;
  • a unique ID;
  • a parent ID;
  • a row count in values; and
  • the aggregated continuous score in colors.
import plotly.graph_objects as go
figure = go.Figure(
go.Sunburst(
labels=plot_data.labels,
ids=plot_data.ids,
parents=plot_data.parents,
values=plot_data.values,
branchvalues="total",
marker={
"colors": plot_data.colors,
"colorscale": "Viridis",
"colorbar": {"title": "Median risk score"},
},
)
)
figure.update_layout(
margin={"t": 30, "l": 0, "r": 0, "b": 0},
)
figure.show()

The same arrays can feed a treemap or another hierarchy renderer.

A string aggregator is applied to the score Series. A callable receives the full DataFrame for the root and each grouped branch in v0.1.16.

import pandas as pd
def upper_quartile_score(group: pd.DataFrame) -> float:
return float(group["risk_score"].quantile(0.75))
plotter.set_aggregator(upper_quartile_score)
plot_data = plotter.compile(container="All observations")

The callable must return one scalar per node.

Use Hierarchy, HLevel, and HItem when the next column depends on the current branch.

from model_auditor.plotting.schemas import Hierarchy, HItem, HLevel
hierarchy = Hierarchy(
levels=[
HLevel(
[
HItem(name="region_type"),
]
),
HLevel(
[
HItem(
name="urban_density",
query="region_type == 'Urban'",
),
HItem(
name="rural_access",
query="region_type == 'Rural'",
),
]
),
HLevel(
[
HItem(name="age_group"),
]
),
]
)
plotter.set_features(hierarchy)
plot_data = plotter.compile(container="All observations")

An item’s query is evaluated against the current hierarchy branch. The item is selected only when the expression is true for every row in that branch. It is not a row-level filter.

At a level where multiple items are valid, Model Auditor concatenates their row values with & to form a composite temporary feature.

A score is optional:

count_plotter = HierarchyPlotter()
count_plotter.set_data(data)
count_plotter.set_features(["region", "age_group"])
plot_data = count_plotter.compile(
container="All observations",
)

The method emits a warning and appends None for node colors.

Hierarchy grouping uses pandas with observed=False. Unused categories can therefore appear as zero-count or NaN-colored nodes, depending on the aggregation path. Remove unused categories first when the chart should show only observed combinations:

data["region"] = data["region"].cat.remove_unused_categories()

Null grouping values are not represented as ordinary groups by default.

The hierarchy API does not calculate performance metrics or bootstrap intervals. Join externally prepared values or create a custom renderer when the chart needs those quantities.

See Hierarchical plot data and Plotting API for exact schemas.