Skip to content

fix: decide reference percent-vs-fraction scale per column, not table-wide - #532

Merged
yakew7 merged 1 commit into
yakew7:mainfrom
propcgamer20-png:fix/parse-reference-per-column-scale
Sep 9, 2026
Merged

fix: decide reference percent-vs-fraction scale per column, not table-wide#532
yakew7 merged 1 commit into
yakew7:mainfrom
propcgamer20-png:fix/parse-reference-per-column-scale

Conversation

@propcgamer20-png

Copy link
Copy Markdown
Collaborator

Problem

faircode/profiler.py's parse_reference (and the JS twin parseReference in assets/profiler-engine.js) made the percent-vs-fraction decision once, globally, across the entire reference file:

scale = 100.0 if any(s > 1.5 for _, _, s in raw) else 1.0

A reference file assembled from multiple sources - one column already given as fractions, another as percentages - gets the wrong scale applied to whichever column didn't trigger the heuristic.

Repro (before)

ref_mixed.csv with sex as fractions and race as percentages:

column,group,share
sex,Female,0.6
sex,Male,0.4
race,White,70
race,Black,20
race,Other,10

race's 70 trips the 1.5 threshold, so scale = 100 is applied table-wide, dividing sex's correct 0.6/0.4 down to 0.006/0.004. The sex reference comparison becomes nonsense (0.4-0.6% expected vs 50% actual).

Fix

Group rows by the column identifier and decide the scale per column:

by_col = {}
for col, grp, share in raw:
    by_col.setdefault(col, []).append((grp, share))
reference = {}
for col, pairs in by_col.items():
    scale = 100.0 if any(s > 1.5 for _, s in pairs) else 1.0
    for grp, share in pairs:
        reference.setdefault(col, {})[grp] = share / scale

Same change mirrored in assets/profiler-engine.js (Python/JS parity), and SPEC.md section 9 updated. Single-convention files parse exactly as before.

After

parse_reference(ref_mixed) -> {"sex": {"Female": 0.6, "Male": 0.4}, "race": {"White": 0.7, "Black": 0.2, "Other": 0.1}}

Tests

  • test_parse_reference_mixed_scale_is_decided_per_column (test_profiler.py)
  • test_python_js_parse_reference_mixed_scale_parity (test_js_parity.py) - runs parseReference under Node and asserts byte-identical result to the Python engine

pytest tests/test_profiler.py tests/test_js_parity.py -> 61 passed, 1 failed. The failure (test_python_js_profiler_parity_sniffs_quoted_newlines) is pre-existing on main on this platform and unrelated. ruff clean.

Closes #513

🤖 Generated with Claude Code

…-wide

parse_reference (and its JS twin parseReference) picked one global scale
for the whole reference file: "if any value exceeds 1.5, read the whole
table as percentages". A reference file assembled from multiple sources
(one column already in fractions, another in percentages) then got the
wrong scale applied to whichever column didn't trip the heuristic - e.g.
a `race` column given as 70/20/10 forced scale=100 onto a `sex` column's
already-correct 0.6/0.4, turning it into 0.006/0.004 and producing
nonsense deviation numbers with no warning.

The scale is now decided per column (rows grouped by the `column`
identifier). Single-convention files are unaffected. Updated in both
engines plus SPEC.md section 9.

Closes yakew7#513

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@propcgamer20-png is attempting to deploy a commit to the yashkewlani2020-gmailcom's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

@yakew7 @ahmdkaml - new PR touching a path you own, please review.

@yakew7
yakew7 merged commit 4e8bfe0 into yakew7:main Sep 9, 2026
17 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parse_reference's percent-vs-fraction heuristic is table-wide, corrupting correctly-scaled columns in a mixed-format reference file

2 participants