fix(correlation): keep empty diagonals when building z_critical (#320) - #1262
fix(correlation): keep empty diagonals when building z_critical (#320)#1262abdulsamie10 wants to merge 1 commit into
Conversation
valuation_correlation() raised
ValueError: Shape of passed values is (1, 10), indices imply (1, 9)
on triangles missing their earliest diagonals. z_critical was built with
.dropna(), which drops diagonals that are entirely NaN, while self.probs
keeps one entry per link-ratio diagonal. Slicing by valuation instead
keeps the empty diagonals so the columns stay aligned (casact#320).
Output is byte-identical on complete triangles. Also renames the
ambiguous I to num_dev_periods so the file no longer needs its E741
per-file lint suppression.
There was a problem hiding this comment.
🟢 Approval recommended
The fix directly addresses the reported shape-mismatch failure mode and includes a targeted regression test to prevent recurrence.
Pull request overview
This PR fixes ValuationCorrelation(..., total=False).z_critical failing on incomplete triangles whose earliest diagonals are entirely missing (issue #320) by constructing the z_critical triangle in a way that preserves all-NaN diagonals so its ddims stay aligned with self.probs.
Changes:
- Rebuild
z_criticalvia valuation slicing (instead ofdropna) to keep empty diagonals and avoid shape mismatches on repr/display. - Clean up Ruff linting by renaming an ambiguous variable (
I→num_dev_periods) and removing the now-unneeded per-file ignore. - Add a regression test covering incomplete triangles (including numpy + sparse backends via the
xyzfixture).
File summaries
| File | Description |
|---|---|
pyproject.toml |
Removes the Ruff per-file ignore for E741 now that the underlying ambiguity is fixed. |
chainladder/core/tests/test_correlation.py |
Adds a regression test ensuring z_critical remains well-formed and printable for incomplete triangles (#320). |
chainladder/core/correlation.py |
Preserves empty diagonals when building z_critical (fixing the ValueError) and renames I to a non-ambiguous identifier. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@abdulsamie10 welcome! thanks for picking up this old bug. looks to be a single line fix? curious how you came upon our repo and what your interest in actuarial science is |
Pyright Type CompletenessView the full Project (full
Other symbols referenced but not exported by
Symbols without documentation:
Patch (exported symbols added or changed by this PR): 0.0% fully typed (0 / 1)
Patch symbol details
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1262 +/- ##
=======================================
Coverage 91.70% 91.70%
=======================================
Files 93 93
Lines 5435 5435
Branches 699 699
=======================================
Hits 4984 4984
Misses 327 327
Partials 124 124
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary of Changes
Fixes the
ValueErrorfrom #320:valuation_correlation(total=False).z_criticalcrashedon any triangle whose earliest diagonals are entirely missing (e.g.
load_sample('xyz'),the Friedland XYZ insurer data from the issue).
self.probsalways has one column per link-ratio diagonal, but thez_criticalframe itis written into was built with
.dropna(), which also drops interior all-NaN diagonals.On triangles with missing leading diagonals the frame ended up with fewer ddims than value
columns, and repr (or anything else that walks ddims) raised
ValueError: Shape of passed values is (1, 10), indices imply (1, 9).The fix builds the frame by valuation slicing instead, so empty diagonals keep their
column and stay aligned with
probs:against the old construction on raa, clrd, quarterly and genins).
test non-significant (False). If you'd rather surface those as NaN it would need a dtype
change away from bool — happy to discuss, this PR keeps the minimal behavior.
Because the Ruff workflow lints changed files with per-file-ignores cleared, this also
fixes the pre-existing E741 in
DevelopmentCorrelation(I→num_dev_periods, purerename), removes the corresponding per-file-ignore from
pyproject.toml, and appliesruff format(0.16.1) to the two touched files.Added
test_val_corr_incomplete_triangleusing the existingxyzfixture, which runs onboth the numpy and sparse backends. It fails on main and passes with this change.
Related GitHub Issue(s)
Fixes #320
Additional Context for Reviewers
The one behavioral question worth a reviewer's eye: for diagonals with no data,
z_criticalnow reports False (not significant) rather than being silently dropped fromthe output. That matches the "partial results" option discussed in the issue, and keeps
the column count consistent with
z,z_expectationandz_variance.Local runs:
uv run pytest→ 1129 passed, 8 skipped.ruff check(with per-file-ignorescleared) and
ruff format --checkare clean on the changed files with ruff 0.16.1.