Rule Fairness#

Functions#

compute_subgroup_metrics#

iguanas.rule_fairness.compute_subgroup_metrics(R: polars.DataFrame, y: polars.Series, group_col: polars.Series, weights: polars.Series | None = None, betas: list[float] | None = None) polars.DataFrame[source]#

Compute rule performance metrics broken down by a protected attribute.

Evaluates each rule’s precision, recall, and other metrics within every subgroup defined by the unique values of group_col. Useful for detecting disparate impact — e.g. a rule that has high precision overall but systematically mis-fires on a particular demographic group.

Parameters:
  • R (pl.DataFrame) – Boolean DataFrame of rule predictions (columns = rules, rows = samples).

  • y (pl.Series) – Target series (boolean or binary).

  • group_col (pl.Series) – Series defining subgroup membership. Any dtype is supported; unique values define the groups. Must have the same length as R and y.

  • weights (pl.Series | None, default=None) – Optional sample weights. Forwarded to compute_metrics() for each subgroup.

  • betas (list[float] | None, default=None) – F-beta values to compute. Forwarded to compute_metrics().

Returns:

Long-format DataFrame with one row per (group, rule) pair. Columns:

  • group — subgroup label

  • group_size — number of samples in that group

  • rule — rule expression string

  • All metric columns from compute_metrics() (TP, FP, precision, recall, f1, …)

Sorted by group then rule. Returns an empty DataFrame if R is empty.

Return type:

pl.DataFrame

Examples

>>> import polars as pl
>>> R = pl.DataFrame({
...     "rule_A": [True,  False, True,  False, True],
...     "rule_B": [False, True,  False, True,  True],
... })
>>> y = pl.Series([1, 0, 1, 0, 1])
>>> group = pl.Series(["M", "M", "F", "F", "F"])
>>> compute_subgroup_metrics(R, y, group)

See also

compute_metrics

Aggregate (non-split) metric computation.

compute_disparate_impact_ratio#

iguanas.rule_fairness.compute_disparate_impact_ratio(subgroup_df: polars.DataFrame, reference_group: str, metric: str = 'precision') polars.DataFrame[source]#

Compute the disparate-impact ratio relative to a reference group.

For each rule and each non-reference group, the ratio is:

\[\text{DIR} = \frac{\text{metric}_{\text{group}}}{\text{metric}_{\text{reference}}}\]

A ratio below 0.8 (the “four-fifths rule”) typically signals potentially disparate impact under US EEOC guidelines.

Parameters:
  • subgroup_df (pl.DataFrame) – Output of compute_subgroup_metrics() — must contain columns group, rule, and the requested metric.

  • reference_group (str) – The group whose metric value is used as the denominator.

  • metric (str, default="precision") – Name of the metric column to use for the ratio.

Returns:

One row per (rule, group) pair for non-reference groups with columns:

  • rule

  • group

  • {metric}_group — metric value for this group

  • {metric}_reference — metric value for the reference group

  • disparate_impact_ratio — ratio (group / reference); null when reference metric is zero or null.

Sorted by rule then disparate_impact_ratio ascending.

Return type:

pl.DataFrame

Examples

>>> subgroup_df = compute_subgroup_metrics(R, y, group_col)
>>> compute_disparate_impact_ratio(subgroup_df, reference_group="1", metric="precision")

See also

compute_subgroup_metrics

Compute per-subgroup metrics first.