Export and style results
Model Auditor result objects support four distinct reporting needs:
- exact numeric access through nested dataclasses;
- unrounded long-form exports through
to_numeric_dataframe(); - compact display tables through
to_dataframe(); and - optional relative notebook coloring through
style_dataframe().
Use the representation that matches the next consumer.
Access numeric values
Section titled “Access numeric values”For calculations, select the LevelMetric object:
metric = ( results.features["region"] .levels["North"] .metrics["sensitivity"])
score = float(metric.score)lower, upper = metric.intervalThis path preserves numeric types.
The hierarchy is:
ScoreEvaluation → FeatureEvaluation → LevelEvaluation → LevelMetricSee Schemas and result objects for every field.
Create a display table
Section titled “Create a display table”For analysis and durable export, start with:
numeric_long = results.to_numeric_dataframe()metadata = numeric_long.attrs["metadata"]Each row contains stable score, feature, level, and metric identifiers plus the estimate, bounds, support, interval diagnostics, direction, parameters, and excluded-row count.
table = results.to_dataframe( n_decimals=3, metric_labels=False,)Default columns use stable metric names such as sensitivity, auroc, and n_pos.
Use display labels when preparing a human-facing table:
labeled_table = results.to_dataframe( n_decimals=2, metric_labels=True,)Cells are formatted strings. A CI-bearing metric appears as:
0.81 (0.74, 0.87)A count appears with integer formatting. Do not feed this table directly into numeric aggregation without parsing it.
Export one feature or level
Section titled “Export one feature or level”region_table = results.features["region"].to_dataframe( metric_labels=True,)
north_table = ( results.features["region"] .levels["North"] .to_dataframe(metric_labels=True))FeatureEvaluation.to_dataframe() uses feature levels as rows. LevelEvaluation.to_dataframe() creates one row.
The add_index option can add a feature or score label as an outer index at the feature and score scopes. The level method retains an add_index argument for API consistency but does not use it in v0.1.16.
Preserve intentional row order
Section titled “Preserve intentional row order”Use a categorical dtype before add_data():
data["severity"] = pd.Categorical( data["severity"], categories=["Low", "Moderate", "High", "Critical"], ordered=True,)All declared categories appear in performance and error tables in that order. An unobserved category remains as an explicit NaN row.
Apply relative notebook styling
Section titled “Apply relative notebook styling”display( results.features["region"].style_dataframe( n_decimals=3, metric_labels=True, rank=True, ))Styling is neutral by default. With rank=True, eligible metric columns are
divided into relative thirds:
- high tier:
#d4edda; - medium tier:
#fff3cd; - low tier:
#f8d7da.
FPR and FNR are automatically inverted so lower values receive the high tier. Count metrics are not styled unless requested:
display( results.style_dataframe( metric_labels=True, include_count_metrics=True, ))Custom colors are supported:
styled = results.style_dataframe( low_color="#fde2e2", medium_color="#fff4c2", high_color="#d9f2df",)Metric direction controls ranking. Counts, prevalence, calibration intercept
and slope, and enrichment odds ratios receive no performance coloring.
Export error analysis differently
Section titled “Export error analysis differently”error_table = error_results.to_dataframe(metric_labels=False)ErrorEvaluation.to_dataframe() is numeric, not display-formatted. It returns MultiIndex columns for support, percentages, odds ratios, and CI bounds. Its n_decimals argument is retained for compatibility but does not round the numeric output.
For a compact notebook view:
display( error_results.style_dataframe( n_decimals=3, metric_labels=True, ))The styled error view folds CI bounds into the odds-ratio display and colors only the odds-ratio columns.
Write files
Section titled “Write files”Use the display table for presentation-oriented CSV output:
labeled_table.to_csv("subgroup-performance-display.csv")Use explicitly extracted numeric records for analysis. One practical pattern is:
records = []
for feature_name, feature in results.features.items(): for level_name, level in feature.levels.items(): for metric_name, metric in level.metrics.items(): records.append( { "feature": feature_name, "level": level_name, "metric": metric_name, "score": metric.score, "ci_lower": None if metric.interval is None else metric.interval[0], "ci_upper": None if metric.interval is None else metric.interval[1], } )
numeric_long = pd.DataFrame.from_records(records)numeric_long.to_parquet("subgroup-performance.parquet", index=False)This avoids parsing formatted strings and gives each metric one long-form row.