Skip to content

profiler.py's age-band classifier silently absorbs negative age sentinels into the '75+' band #431

Description

@yakew7

Where: faircode/profiler.py's _age_to_numeric/_age_band (age dimension banding).

The gap: _age_band checks edges[i] <= num < edges[i+1] for AGE_BANDS = [0,18,30,45,60,75]; any number below 0 falls through every branch and returns the "75+" fallback instead of being treated as unbandable. Real datasets commonly use -1/-999 as an "unknown age" sentinel.

Repro:

>>> import pandas as pd
>>> from faircode import profile
>>> df = pd.DataFrame({'age': [25,30,45,22,60,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]})
>>> profile(df)['dimensions'][0]['groups'][0]
{'label': '75+', 'count': 10, 'share': 0.6666666666666666, ...}

10 of 15 rows (66.7%) are sentinel values fabricated into a "75+" majority; missing_pct stays 0.0 and no flag mentions the sentinel at all.

There's also a related inconsistency in the same function: a string "-5" (the numeric-extraction regex \d+ strips the sign) bands as "0-18", while a numeric -5.0 bands as "75+" - the same logical value produces two different wrong answers depending on dtype.

Why it matters: silently mislabels a fairness dimension - a data-quality sentinel becomes a phantom elderly majority with zero flag, for a tool whose whole design philosophy is "loud failure over silent wrong result" (see the JSON-orientation and manifest-validation fixes elsewhere in this repo).

Suggested fix: in _age_to_numeric, reject negative numbers (return None) before the string/numeric branches diverge; in _age_band, treat num < edges[0] as unbandable (None) rather than falling through to the last band.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions