diff --git a/CHANGELOG.md b/CHANGELOG.md index 09a0112..3922f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project are documented in this file. +## Unreleased + +### Changed +- **The release-mode minimum `number_of_cases` threshold for `applied_to_treat` edges is now 10 instead of 25.** `drop_low_number_of_cases` keeps edges whose case count is >= 10 (nulls kept, as before); release builds now ship `applied_to_treat` edges backed by 10-24 cases that earlier releases dropped. Gating (`--release` *and* `applied_to_treat`), null handling, non-numeric tolerance, and `significance`-phase placement are unchanged. + ## 16.6.2 - 2026-09-04 ### Fixed diff --git a/src/tablassert/lib.py b/src/tablassert/lib.py index 31f82d6..c0892c7 100644 --- a/src/tablassert/lib.py +++ b/src/tablassert/lib.py @@ -1058,7 +1058,7 @@ def drop_zero_effect_size(lf: pl.LazyFrame, col: str = "effect_size") -> pl.Lazy return lf.filter(pl.col(col).cast(pl.Float64, strict=False).ne_missing(0.0)) -def drop_low_number_of_cases(lf: pl.LazyFrame, col: str = "number_of_cases", threshold: float = 25.0) -> pl.LazyFrame: +def drop_low_number_of_cases(lf: pl.LazyFrame, col: str = "number_of_cases", threshold: float = 10.0) -> pl.LazyFrame: """Drop release-mode ``applied_to_treat`` edges whose number of cases is below the threshold. Args: diff --git a/tests/test_lib.py b/tests/test_lib.py index 95b93c9..081037b 100644 --- a/tests/test_lib.py +++ b/tests/test_lib.py @@ -1309,11 +1309,11 @@ def test_drop_zero_effect_size_noop_without_column() -> None: def test_drop_low_number_of_cases_removes_below_threshold_keeps_at_threshold_and_nulls() -> None: - """drop_low_number_of_cases drops case counts under 25 while keeping 25+ and nulls.""" - lf: pl.LazyFrame = pl.DataFrame({"subject": ["a", "b", "c", "d", "e"], "number_of_cases": [24, 25, 26, None, 0]}).lazy() + """drop_low_number_of_cases drops case counts under 10 while keeping 10+ and nulls.""" + lf: pl.LazyFrame = pl.DataFrame({"subject": ["a", "b", "c", "d", "e"], "number_of_cases": [9, 10, 11, None, 0]}).lazy() result: pl.DataFrame = drop_low_number_of_cases(lf).collect() assert list(result["subject"]) == ["b", "c", "d"] - assert list(result["number_of_cases"]) == [25, 26, None] + assert list(result["number_of_cases"]) == [10, 11, None] def test_drop_low_number_of_cases_noop_without_column() -> None: @@ -1328,7 +1328,7 @@ def test_drop_low_number_of_cases_keeps_non_numeric_cells() -> None: """drop_low_number_of_cases keeps non-numeric cells (a header row read as data) instead of crashing on a strict cast.""" # The csv op reads sources with has_header=False, so a TSV's header row flows # through as a data row; the strict cast raised InvalidOperationError on it. - lf: pl.LazyFrame = pl.DataFrame({"subject": ["hdr", "a", "b", "c"], "number_of_cases": ["number_of_cases", "30", "10", None]}).lazy() + lf: pl.LazyFrame = pl.DataFrame({"subject": ["hdr", "a", "b", "c"], "number_of_cases": ["number_of_cases", "30", "9", None]}).lazy() result: pl.DataFrame = drop_low_number_of_cases(lf).collect() assert list(result["subject"]) == ["hdr", "a", "c"]