Skip to content

Commit 83aff13

Browse files
Fix single-variable rake fallback support metadata
1 parent e53ac1a commit 83aff13

2 files changed

Lines changed: 66 additions & 4 deletions

File tree

balance/weighting_methods/rake.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,12 @@ def rake(
312312
}
313313
if store_fit_metadata:
314314
cell_ratio = post["model"]["cell_weight_ratio"]
315-
categories = [[str(x) for x in cell_ratio.index]]
315+
supported_ratio = cell_ratio[np.isfinite(cell_ratio.to_numpy(dtype=float))]
316+
categories = [[str(x) for x in supported_ratio.index]]
316317
m_sample = np.ones(len(categories[0]), dtype=np.float64)
317-
m_fit = (cell_ratio.to_numpy(dtype=np.float64) * m_sample).reshape(-1)
318+
m_fit = (supported_ratio.to_numpy(dtype=np.float64) * m_sample).reshape(-1)
319+
sample_index = post["model"]["sample_index"]
320+
target_index = post["model"]["target_index"]
318321
model.update(
319322
{
320323
"store_fit_metadata": True,
@@ -328,8 +331,8 @@ def rake(
328331
"na_action": post["model"]["na_action"],
329332
"transformations": post["model"]["transformations"],
330333
"transformations_origin": transformations,
331-
"training_sample_weights": sample_weights.copy(),
332-
"training_target_weights": target_weights.copy(),
334+
"training_sample_weights": sample_weights.loc[sample_index].copy(),
335+
"training_target_weights": target_weights.loc[target_index].copy(),
333336
"weight_trimming_mean_ratio": weight_trimming_mean_ratio,
334337
"weight_trimming_percentile": weight_trimming_percentile,
335338
"keep_sum_of_weights": keep_sum_of_weights,

tests/test_rake.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,65 @@ def test_rake_single_variable_default_transform_with_na_predict_works(self) -> N
340340
self.assertEqual(predicted.shape[0], sample_df.shape[0])
341341
self.assertTrue(np.isfinite(predicted.fillna(0).to_numpy()).all())
342342

343+
def test_rake_single_variable_target_only_levels_rejected_in_transfer(self) -> None:
344+
sample_df = pd.DataFrame({"x": ["a", "a", "b", "b"]})
345+
target_df = pd.DataFrame({"x": ["a", "a", "b", "b", "c"]})
346+
sample_w = pd.Series([1.0, 1.0, 1.0, 1.0])
347+
target_w = pd.Series([1.0] * len(target_df))
348+
349+
fitted = rake(
350+
sample_df=sample_df,
351+
sample_weights=sample_w,
352+
target_df=target_df,
353+
target_weights=target_w,
354+
variables=["x"],
355+
transformations=None,
356+
store_fit_metadata=True,
357+
)
358+
new_sample_df = pd.DataFrame({"x": ["a", "c"]})
359+
new_sample_w = pd.Series([1.0, 1.0])
360+
with self.assertRaisesRegex(
361+
ValueError, "do not map to stored fit-time categories"
362+
):
363+
_predict_weights_from_model(
364+
model=fitted["model"],
365+
sample_df=new_sample_df,
366+
sample_weights_full=new_sample_w,
367+
target_df=target_df,
368+
target_weights=target_w,
369+
is_transfer=True,
370+
)
371+
372+
def test_rake_single_variable_drop_na_replay_uses_dropped_target_total(
373+
self,
374+
) -> None:
375+
sample_df = pd.DataFrame({"x": ["a", "b", "a"]})
376+
target_df = pd.DataFrame({"x": ["a", "b", np.nan, "b"]})
377+
sample_w = pd.Series([1.0, 1.0, 1.0])
378+
target_w = pd.Series([1.0, 1.0, 10.0, 1.0])
379+
380+
fitted = rake(
381+
sample_df=sample_df,
382+
sample_weights=sample_w,
383+
target_df=target_df,
384+
target_weights=target_w,
385+
variables=["x"],
386+
transformations=None,
387+
na_action="drop",
388+
store_fit_metadata=True,
389+
)
390+
replay = _predict_weights_from_model(
391+
model=fitted["model"],
392+
sample_df=sample_df,
393+
sample_weights_full=sample_w,
394+
target_df=target_df,
395+
target_weights=target_w,
396+
is_transfer=False,
397+
)
398+
self.assertAlmostEqual(
399+
float(replay.sum()), float(fitted["weight"].sum()), places=8
400+
)
401+
343402
def test_rake_weights(self) -> None:
344403
"""
345404
Test basic rake weighting functionality with categorical data.

0 commit comments

Comments
 (0)