@@ -1301,6 +1301,146 @@ def test_BalanceDF_asmd_aggregate_by_main_covar(self) -> None:
13011301 self .assertEqual (outcome_default , expected_default )
13021302 self .assertEqual (outcome_main_covar , expected_main_covar )
13031303
1304+ def test_BalanceDF__kld_BalanceDF (self ) -> None :
1305+ """Test _kld_BalanceDF static method directly."""
1306+ sample = Sample .from_frame (
1307+ pd .DataFrame (
1308+ {"id" : (1 , 2 ), "a" : (1 , 2 ), "b" : (- 1 , 12 ), "weight" : (1 , 2 )}
1309+ )
1310+ ).covars ()
1311+
1312+ target = Sample .from_frame (
1313+ pd .DataFrame (
1314+ {"id" : (1 , 2 ), "a" : (3 , 4 ), "b" : (0 , 42 ), "weight" : (1 , 2 )}
1315+ )
1316+ ).covars ()
1317+
1318+ result = BalanceDF ._kld_BalanceDF (sample , target )
1319+
1320+ # Verify result is a Series with expected keys
1321+ self .assertIsInstance (result , pd .Series )
1322+ self .assertIn ("a" , result .index )
1323+ self .assertIn ("b" , result .index )
1324+ self .assertIn ("mean(kld)" , result .index )
1325+
1326+ # Verify all values are non-negative (KLD property)
1327+ self .assertTrue ((result >= 0 ).all ())
1328+
1329+ # Test with aggregate_by_main_covar
1330+ result_agg = BalanceDF ._kld_BalanceDF (sample , target , aggregate_by_main_covar = True )
1331+ self .assertIsInstance (result_agg , pd .Series )
1332+
1333+ def test_BalanceDF__emd_BalanceDF (self ) -> None :
1334+ """Test _emd_BalanceDF static method directly."""
1335+ sample = Sample .from_frame (
1336+ pd .DataFrame (
1337+ {"id" : (1 , 2 ), "a" : (1 , 2 ), "b" : (- 1 , 12 ), "weight" : (1 , 2 )}
1338+ )
1339+ ).covars ()
1340+
1341+ target = Sample .from_frame (
1342+ pd .DataFrame (
1343+ {"id" : (1 , 2 ), "a" : (3 , 4 ), "b" : (0 , 42 ), "weight" : (1 , 2 )}
1344+ )
1345+ ).covars ()
1346+
1347+ result = BalanceDF ._emd_BalanceDF (sample , target )
1348+
1349+ # Verify result is a Series with expected keys
1350+ self .assertIsInstance (result , pd .Series )
1351+ self .assertIn ("a" , result .index )
1352+ self .assertIn ("b" , result .index )
1353+ self .assertIn ("mean(emd)" , result .index )
1354+
1355+ # Verify all values are non-negative (EMD property)
1356+ self .assertTrue ((result >= 0 ).all ())
1357+
1358+ # Test with aggregate_by_main_covar
1359+ result_agg = BalanceDF ._emd_BalanceDF (sample , target , aggregate_by_main_covar = True )
1360+ self .assertIsInstance (result_agg , pd .Series )
1361+
1362+ def test_BalanceDF__cvmd_BalanceDF (self ) -> None :
1363+ """Test _cvmd_BalanceDF static method directly."""
1364+ sample = Sample .from_frame (
1365+ pd .DataFrame (
1366+ {"id" : (1 , 2 ), "a" : (1 , 2 ), "b" : (- 1 , 12 ), "weight" : (1 , 2 )}
1367+ )
1368+ ).covars ()
1369+
1370+ target = Sample .from_frame (
1371+ pd .DataFrame (
1372+ {"id" : (1 , 2 ), "a" : (3 , 4 ), "b" : (0 , 42 ), "weight" : (1 , 2 )}
1373+ )
1374+ ).covars ()
1375+
1376+ result = BalanceDF ._cvmd_BalanceDF (sample , target )
1377+
1378+ # Verify result is a Series with expected keys
1379+ self .assertIsInstance (result , pd .Series )
1380+ self .assertIn ("a" , result .index )
1381+ self .assertIn ("b" , result .index )
1382+ self .assertIn ("mean(cvmd)" , result .index )
1383+
1384+ # Verify all values are non-negative (CVMD property)
1385+ self .assertTrue ((result >= 0 ).all ())
1386+
1387+ # Test with aggregate_by_main_covar
1388+ result_agg = BalanceDF ._cvmd_BalanceDF (sample , target , aggregate_by_main_covar = True )
1389+ self .assertIsInstance (result_agg , pd .Series )
1390+
1391+ def test_BalanceDF__ks_BalanceDF (self ) -> None :
1392+ """Test _ks_BalanceDF static method directly."""
1393+ sample = Sample .from_frame (
1394+ pd .DataFrame (
1395+ {"id" : (1 , 2 ), "a" : (1 , 2 ), "b" : (- 1 , 12 ), "weight" : (1 , 2 )}
1396+ )
1397+ ).covars ()
1398+
1399+ target = Sample .from_frame (
1400+ pd .DataFrame (
1401+ {"id" : (1 , 2 ), "a" : (3 , 4 ), "b" : (0 , 42 ), "weight" : (1 , 2 )}
1402+ )
1403+ ).covars ()
1404+
1405+ result = BalanceDF ._ks_BalanceDF (sample , target )
1406+
1407+ # Verify result is a Series with expected keys
1408+ self .assertIsInstance (result , pd .Series )
1409+ self .assertIn ("a" , result .index )
1410+ self .assertIn ("b" , result .index )
1411+ self .assertIn ("mean(ks)" , result .index )
1412+
1413+ # Verify all values are in [0, 1] (KS property)
1414+ self .assertTrue ((result >= 0 ).all ())
1415+ self .assertTrue ((result <= 1 ).all ())
1416+
1417+ # Test with aggregate_by_main_covar
1418+ result_agg = BalanceDF ._ks_BalanceDF (sample , target , aggregate_by_main_covar = True )
1419+ self .assertIsInstance (result_agg , pd .Series )
1420+
1421+ def test_BalanceDF_comparison_functions_invalid_input (self ) -> None :
1422+ """Test that all comparison functions properly validate inputs."""
1423+ sample = Sample .from_frame (
1424+ pd .DataFrame (
1425+ {"id" : (1 , 2 ), "a" : (1 , 2 ), "weight" : (1 , 2 )}
1426+ )
1427+ ).covars ()
1428+
1429+ # Test with non-BalanceDF inputs
1430+ invalid_input = "not a BalanceDF"
1431+
1432+ with self .assertRaisesRegex (ValueError , "must be balancedf_class.BalanceDF" ):
1433+ BalanceDF ._kld_BalanceDF (invalid_input , sample ) # type: ignore
1434+
1435+ with self .assertRaisesRegex (ValueError , "must be balancedf_class.BalanceDF" ):
1436+ BalanceDF ._emd_BalanceDF (sample , invalid_input ) # type: ignore
1437+
1438+ with self .assertRaisesRegex (ValueError , "must be balancedf_class.BalanceDF" ):
1439+ BalanceDF ._cvmd_BalanceDF (invalid_input , sample ) # type: ignore
1440+
1441+ with self .assertRaisesRegex (ValueError , "must be balancedf_class.BalanceDF" ):
1442+ BalanceDF ._ks_BalanceDF (sample , invalid_input ) # type: ignore
1443+
13041444
13051445class TestBalanceDF_to_download (BalanceTestCase ):
13061446 def test_BalanceDF_to_download (self ) -> None :
0 commit comments