From cac3a6d964bbfa89504a90fa45447901de6fcdf2 Mon Sep 17 00:00:00 2001 From: eunwoo song Date: Sun, 6 Sep 2026 13:09:59 +0900 Subject: [PATCH] fix: align missing service-line fallback --- CHANGELOG.md | 6 +++++ CONTRIBUTORS.md | 4 +++ .../preprocessing/_grateful_patient.py | 2 +- tests/test_grateful_patient_featurizer.py | 26 +++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b787728..197b04c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) ## [Unreleased] +### Fixed +- `GratefulPatientFeaturizer` now reports one fallback `general` service line + per known donor when the encounter table omits the service-line column. + Missing physician columns continue to report zero distinct physicians, and + both optional-column paths now have regression coverage. Closes #151. + ### Changed - README coverage badge now links to `pyproject.toml` and reads "≥92% floor" rather than a bare "≥92%". It was a static shields.io string with no tie to diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b40ba47..fc3aa75 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -49,6 +49,10 @@ contribution. Code, docs, tests, and review all count. unit-test coverage for `WealthPercentileTransformer`'s all-missing and partially-missing column branches in `WealthPercentileTransformer` (closes [#169](https://github.com/PhilanthroPy-Project/PhilanthroPy/issues/169)). +- [@be-student](https://github.com/be-student): aligned the missing service-line + fallback with its `general` category and added regression coverage for + missing service-line and physician columns (closes + [#151](https://github.com/PhilanthroPy-Project/PhilanthroPy/issues/151)). ## Getting listed diff --git a/philanthropy/preprocessing/_grateful_patient.py b/philanthropy/preprocessing/_grateful_patient.py index eae1321..8fdc80c 100755 --- a/philanthropy/preprocessing/_grateful_patient.py +++ b/philanthropy/preprocessing/_grateful_patient.py @@ -274,7 +274,7 @@ def fit(self, X, y=None) -> "GratefulPatientFeaturizer": "general", index=grouped.groups.keys() ) summary_parts["distinct_service_lines"] = pd.Series( - 0, dtype=int, index=grouped.groups.keys() + 1, dtype=int, index=grouped.groups.keys() ) if self.physician_col in raw_enc.columns: diff --git a/tests/test_grateful_patient_featurizer.py b/tests/test_grateful_patient_featurizer.py index 331fc58..91fc58a 100755 --- a/tests/test_grateful_patient_featurizer.py +++ b/tests/test_grateful_patient_featurizer.py @@ -133,6 +133,32 @@ def test_missing_drg_weight_col_fills_nan_then_zero_after_transform( "Without drg_weight_col, total_drg_weight must be 0.0 after fillna" ) + def test_missing_service_line_col_falls_back_to_general( + self, enc_df, X_donors + ): + enc = enc_df.drop(columns=["service_line"]) + gpf = GratefulPatientFeaturizer(encounter_df=enc).fit(X_donors) + + result = gpf.transform(X_donors) + feature_names = list(gpf.get_feature_names_out()) + distinct_idx = feature_names.index("distinct_service_lines") + + assert result.shape == (len(X_donors), len(feature_names)) + assert np.isfinite(result).all() + np.testing.assert_array_equal(result[:4, distinct_idx], 1.0) + + def test_missing_physician_col_yields_zero_distinct_physicians( + self, enc_df, X_donors + ): + enc = enc_df.drop(columns=["attending_physician_id"]) + gpf = GratefulPatientFeaturizer(encounter_df=enc).fit(X_donors) + + result = gpf.transform(X_donors) + feature_names = list(gpf.get_feature_names_out()) + physician_idx = feature_names.index("distinct_physicians") + + np.testing.assert_array_equal(result[:4, physician_idx], 0.0) + def test_drg_weight_col_sums_correctly(self, X_donors): """With drg_weight_col present, total_drg_weight must sum DRG weights per donor.""" enc = pd.DataFrame({