|
21 | 21 | from balance import adjustment as balance_adjustment |
22 | 22 | from balance.sample_class import Sample |
23 | 23 | from balance.util import _assert_type |
| 24 | +from balance.weighting_methods.poststratify import poststratify |
24 | 25 | from balance.weighting_methods.rake import ( |
25 | 26 | _find_lcm_of_array_lengths, |
26 | 27 | _hare_niemeyer_allocation, |
@@ -124,14 +125,21 @@ def test_rake_input_assertions(self) -> None: |
124 | 125 | pd.Series((1,) * n_rows), |
125 | 126 | ) |
126 | 127 |
|
127 | | - # Must pass more than one variable |
128 | | - self._assert_rake_raises_with_message( |
129 | | - "Must weight on at least two variables", |
130 | | - sample[["a"]], |
131 | | - pd.Series((1,) * n_rows), |
132 | | - target[["a"]], |
133 | | - pd.Series((1,) * n_rows), |
| 128 | + # A single variable falls back to poststratify. |
| 129 | + with self.assertLogs("balance.weighting_methods", level="WARNING") as cm: |
| 130 | + single_var_result = rake( |
| 131 | + sample_df=sample[["a"]], |
| 132 | + sample_weights=pd.Series((1,) * n_rows), |
| 133 | + target_df=target[["a"]], |
| 134 | + target_weights=pd.Series((1,) * n_rows), |
| 135 | + ) |
| 136 | + self.assertTrue( |
| 137 | + any( |
| 138 | + "falling back to poststratify" in message.lower() |
| 139 | + for message in cm.output |
| 140 | + ) |
134 | 141 | ) |
| 142 | + self.assertIn("weight", single_var_result) |
135 | 143 |
|
136 | 144 | # Must pass weights for sample |
137 | 145 | self._assert_rake_raises_with_message( |
@@ -234,6 +242,46 @@ def test_rake_fails_when_all_na(self) -> None: |
234 | 242 | transformations=None, |
235 | 243 | ) |
236 | 244 |
|
| 245 | + def test_rake_single_variable_matches_poststratify(self) -> None: |
| 246 | + sample_df = pd.DataFrame( |
| 247 | + {"x": ["a", "a", "b", "b", "b"], "noise": [1, 2, 3, 4, 5]} |
| 248 | + ) |
| 249 | + target_df = pd.DataFrame({"x": ["a", "a", "a", "b", "b", "b", "b"]}) |
| 250 | + sample_w = pd.Series([1.0, 2.0, 3.0, 4.0, 5.0]) |
| 251 | + target_w = pd.Series([1.0] * len(target_df)) |
| 252 | + |
| 253 | + with self.assertLogs("balance.weighting_methods", level="WARNING"): |
| 254 | + rake_res = rake( |
| 255 | + sample_df=sample_df, |
| 256 | + sample_weights=sample_w, |
| 257 | + target_df=target_df, |
| 258 | + target_weights=target_w, |
| 259 | + variables=["x"], |
| 260 | + transformations=None, |
| 261 | + na_action="add_indicator", |
| 262 | + weight_trimming_mean_ratio=10.0, |
| 263 | + keep_sum_of_weights=True, |
| 264 | + store_fit_metadata=True, |
| 265 | + ) |
| 266 | + |
| 267 | + post_res = poststratify( |
| 268 | + sample_df=sample_df[["x"]], |
| 269 | + sample_weights=sample_w, |
| 270 | + target_df=target_df[["x"]], |
| 271 | + target_weights=target_w, |
| 272 | + variables=["x"], |
| 273 | + transformations=None, |
| 274 | + na_action="add_indicator", |
| 275 | + weight_trimming_mean_ratio=10.0, |
| 276 | + keep_sum_of_weights=True, |
| 277 | + store_fit_metadata=True, |
| 278 | + ) |
| 279 | + |
| 280 | + pd.testing.assert_series_equal(rake_res["weight"], post_res["weight"]) |
| 281 | + self.assertEqual(rake_res["model"]["method"], "poststratify") |
| 282 | + self.assertTrue(rake_res["model"]["store_fit_metadata"]) |
| 283 | + self.assertIn("cell_weight_ratio", rake_res["model"]) |
| 284 | + |
237 | 285 | def test_rake_weights(self) -> None: |
238 | 286 | """ |
239 | 287 | Test basic rake weighting functionality with categorical data. |
|
0 commit comments