diff --git a/CHANGELOG.md b/CHANGELOG.md index af33b12..3945345 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 - `WealthPercentileTransformer.fit` now raises an actionable `ValueError` when an explicit `wealth_cols` list matches no training column; partial matches diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7424ae9..ff93358 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -56,6 +56,10 @@ contribution. Code, docs, tests, and review all count. schema mismatches fail with actionable diagnostics and preserved automatic and partial-match behavior (closes [#156](https://github.com/PhilanthroPy-Project/PhilanthroPy/issues/156)). +- [@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 35a4be2..e5b62d3 100755 --- a/philanthropy/preprocessing/_grateful_patient.py +++ b/philanthropy/preprocessing/_grateful_patient.py @@ -278,7 +278,7 @@ def fit(self: _Self, X: Any, y: Any = None) -> _Self: "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({