Skip to content

Validate metric inputs and correct metric docs - #109

Merged
kPsarakis merged 1 commit into
fix/one-to-one-tied-scoresfrom
fix/metric-validation-and-docs
Oct 30, 2026
Merged

kPsarakis merged 1 commit into
fix/one-to-one-tied-scoresfrom
fix/metric-validation-and-docs

Conversation

@kPsarakis

Copy link
Copy Markdown
Member

Stack: 3 of 3. #106 → #107 → this PR. Based on #107, so the diff shows only this change. Merge #106 and #107 first.

Smaller problems found while investigating #105, each reproduced before fixing.

Ground truth

  • Any iterable works. A set raised TypeError: 'set' object is not subscriptable. A generator was consumed by the first metric, so the others saw empty ground truth. get_metrics() now materialises it once.
  • Duplicates count once. [("a","a"), ("a","a"), ("b","b")] was counted twice in recall but once in precision, giving Recall 2/3 instead of 1/2. RecallAtSizeofGroundTruth now sizes its cutoff from the deduplicated ground truth.
  • Mixed formats raise ValueError. The format was decided from the first entry only. Column-name pair first, then a ColumnPair: the ColumnPair was compared as (table, column) and silently counted as a miss. The other order raised IndexError. Entries with other than 2 or 4 fields also raise.

Other inputs

  • PrecisionTopNPercent: raises for n outside 0–100. Previously n=150 was reported as "PrecisionTop150Percent" but computed at 100%. A fractional n is now used as given; n=12.5 used to compute with 12 while its name said 12.5.
  • take_top_n(): rejects a negative n. take_top_n(-1) used to drop the last item.
  • take_top_percent(): rejects values outside 0–100. take_top_percent(-50) used to keep 2 of 3.
  • get_metrics(): rejects an unknown one_to_one_method up front. It was silently accepted when no metric used 1:1 selection.

Docs

  • Default threshold: the 1:1 selectors' docstrings and docs/results.md called it "the median". It's the distinct score at index ceil(k/2) from the top, which is at or below the median; with 3 distinct scores it's the lowest. I documented the existing rule rather than changing it, since a change would shift every published score.
  • MeanReciprocalRank: the docstring now says it averages per ground-truth source column using per-source rank. That's what the code computes and what docs/metrics.md already said.
  • docs/metrics.md:
    • explains how column-name ground truth behaves with more than two tables
    • notes that any iterable is accepted, duplicates count once, and mixed formats raise
    • gives the range of PrecisionTopNPercent(n=...)

Compatibility

The new ValueErrors replace silently wrong results or unrelated errors, and they're listed under Changed in the changelog.

Tests

New TestGroundTruthInput and TestTopSelectionValidation in tests/test_metrics.py. 13 of these tests and subtests fail on #107 without this change. Full suite: 327 passed locally.

🤖 Generated with Claude Code

Ground truth:
- accept any iterable (sets raised TypeError; a generator was seen only
  by the first metric) and count duplicate entries once (they were
  counted twice in recall but once in precision)
- raise ValueError for entries mixing column-name pairs with ColumnPair
  (one order silently compared table names as column names, the other
  raised IndexError) or with other than 2 or 4 fields
- RecallAtSizeofGroundTruth sizes its cutoff from the deduplicated
  ground truth

Other inputs:
- PrecisionTopNPercent raises for n outside 0-100 instead of clamping
  silently, and uses a fractional n as given instead of truncating it
  while reporting the fraction in its name
- take_top_n() rejects negative n, take_top_percent() rejects values
  outside 0-100 (negative values sliced from the end)
- get_metrics() rejects an unknown one_to_one_method up front, even
  when no metric uses 1:1 selection

Docs:
- describe the 1:1 selectors' default threshold accurately: it is at
  or below the median of the distinct scores, not the median
- MeanReciprocalRank averages over ground-truth source columns using
  per-source rank, as the code does
- note how column-name ground truth behaves with more than two tables

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.29%. Comparing base (99f2d20) to head (9232a22).

Additional details and impacted files

Impacted file tree graph

@@                      Coverage Diff                       @@
##           fix/one-to-one-tied-scores     #109      +/-   ##
==============================================================
+ Coverage                       95.27%   95.29%   +0.02%     
==============================================================
  Files                              53       53              
  Lines                            2833     2846      +13     
  Branches                          443      448       +5     
==============================================================
+ Hits                             2699     2712      +13     
  Misses                             83       83              
  Partials                           51       51              
Flag Coverage Δ
unit 95.29% <100.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
valentine/algorithms/matcher_results.py 98.75% <100.00%> (+0.05%) ⬆️
valentine/metrics/metric_helpers.py 100.00% <100.00%> (ø)
valentine/metrics/metrics.py 90.00% <100.00%> (+0.30%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@kPsarakis
kPsarakis merged commit a725a04 into master Oct 30, 2026
31 checks passed
@kPsarakis
kPsarakis deleted the fix/metric-validation-and-docs branch October 30, 2026 11:46
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.

1 participant