SuperModelingFactory 0.5.9__tar.gz → 0.5.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Binning_Tool.py +57 -29
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Binning_Tool.pyi +1 -1
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/utils.py +22 -21
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Master.py +27 -14
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Tool.py +189 -103
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Tool.pyi +1 -1
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/__init__.py +1 -1
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/PKG-INFO +2 -2
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/README.md +1 -1
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/PKG-INFO +2 -2
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/pyproject.toml +1 -1
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/setup.py +1 -1
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/ExcelMaster/ExcelFormatTool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/ExcelMaster/ExcelMaster.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/ExcelMaster/Template.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/ExcelMaster/Utility.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/ExcelMaster/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/LICENSE +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/MANIFEST.in +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Check_DuckDB_Compatibility.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Json_Data_Converter.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Model_Registry_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/ODPS_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Parallel_Engine.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Parallel_ODPS_Manager.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Proc_Compare.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Slope_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Slope_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/XOR_Encryptor.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/XOR_Encryptor.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/kDataFrame.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/kDataFrame.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/sample_weight_utils.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Evaluation_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Evaluation_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Model_Eval_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Model_Eval_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/evaluate_model.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/evaluate_model.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/weighted_eval_utils.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Explainability/Coalition_Structure.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Explainability/Model_Explainer.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Explainability/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Distribution_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Distribution_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Feature_Insights.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Feature_Insights.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Feature_Screen.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/PSI_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/PSI_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/WOE_Engine_Feature_Patch.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Weighted_Screen.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/Backward_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/Backward_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/GBM_Search_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/GBM_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/GBM_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/LRM_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/LRM_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/_common.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/credit_model.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/feature_validation.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/field_meta.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/mock_sample.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/orchestrator.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/reject_inference.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/sample_analysis.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/score_comparison.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/score_consistency_uat.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/screening_artifact.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Distribution_Adaptation.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Distribution_Adaptation.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Reject_Infer.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Reject_Infer.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Sample_Split.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Sample_Split.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/UAT/UAT_Consistency_Checker.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/UAT/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Adapter.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Adapter.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Master.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Monotone_Binner.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Monotone_Binner.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Plot_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Plot_Tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Report_Builder.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Report_Builder.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/plot_woe_tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/plot_woe_tool.pyi +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/_utils/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/_utils/nan_guard.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/_utils/robust.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/_utils/sentinels.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/ref_font/KaiTi.ttf +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/ref_font/WeiRuanYaHei.ttf +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/ref_font/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/ref_font/simsun.ttc +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Report/Report_Tool.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Report/__init__.py +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/SOURCES.txt +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/dependency_links.txt +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/not-zip-safe +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/requires.txt +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/top_level.txt +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/requirements.txt +0 -0
- {supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/setup.cfg +0 -0
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Binning_Tool.py
RENAMED
|
@@ -706,6 +706,46 @@ def get_bin_range(edges, precision = 5, ascending = False, left_sign = '(', righ
|
|
|
706
706
|
return res
|
|
707
707
|
|
|
708
708
|
|
|
709
|
+
def _materialize_bin_columns(data, binned, bin_range_list, bin_num_col, bin_range_col):
|
|
710
|
+
"""Attach categorical bin numbers and labels without Python row callbacks."""
|
|
711
|
+
codes = binned.cat.codes.to_numpy(dtype=np.intp, copy=False)
|
|
712
|
+
range_values = np.empty(len(codes), dtype=object)
|
|
713
|
+
range_values[:] = np.nan
|
|
714
|
+
valid = codes >= 0
|
|
715
|
+
if valid.any():
|
|
716
|
+
labels = np.asarray(bin_range_list, dtype=object)
|
|
717
|
+
if codes[valid].max() >= len(labels):
|
|
718
|
+
raise ValueError("Binning category codes do not match bin range labels")
|
|
719
|
+
range_values[valid] = np.take(labels, codes[valid])
|
|
720
|
+
|
|
721
|
+
data[bin_num_col] = binned.astype(object)
|
|
722
|
+
data[bin_range_col] = range_values
|
|
723
|
+
return data
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def _parse_bin_range_bounds(data, col="_bin_range"):
|
|
727
|
+
"""Parse interval labels into numeric left and right bounds vectorially."""
|
|
728
|
+
if col not in data.columns:
|
|
729
|
+
raise KeyError(f"Column {col!r} is not present in the bin mapping table")
|
|
730
|
+
|
|
731
|
+
ranges = data[col].astype("string").str.strip()
|
|
732
|
+
bounds = ranges.str.extract(
|
|
733
|
+
r"^[\[\(]\s*([^,]+?)\s*,\s*([^\]\)]+?)\s*[\]\)]$",
|
|
734
|
+
expand=True,
|
|
735
|
+
)
|
|
736
|
+
invalid = bounds.isna().any(axis=1)
|
|
737
|
+
if invalid.any():
|
|
738
|
+
examples = ranges.loc[invalid].dropna().head(3).tolist()
|
|
739
|
+
raise ValueError(f"Unable to parse bin range labels in {col!r}: {examples}")
|
|
740
|
+
|
|
741
|
+
try:
|
|
742
|
+
left = bounds.iloc[:, 0].str.strip().astype(float).to_numpy()
|
|
743
|
+
right = bounds.iloc[:, 1].str.strip().astype(float).to_numpy()
|
|
744
|
+
except (TypeError, ValueError) as exc:
|
|
745
|
+
raise ValueError(f"Bin range column {col!r} contains non-numeric bounds") from exc
|
|
746
|
+
return left, right
|
|
747
|
+
|
|
748
|
+
|
|
709
749
|
def get_bin_range_list(data, col = "_bin_range"):
|
|
710
750
|
"""
|
|
711
751
|
将分箱区间字符串列转换为边界值列表。
|
|
@@ -730,21 +770,8 @@ def get_bin_range_list(data, col = "_bin_range"):
|
|
|
730
770
|
>>> unique_range = get_bin_range_list(data, col="bin_range")
|
|
731
771
|
"""
|
|
732
772
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
.replace("(", "")\
|
|
736
|
-
.replace(")", "")\
|
|
737
|
-
.split(","))
|
|
738
|
-
bin_range = [np.inf if v.strip() == 'inf' else -np.inf if v.strip() == '-inf' else float(v.strip()) for x in data["bin_value_list"].tolist() for v in x]
|
|
739
|
-
|
|
740
|
-
unique_range = []
|
|
741
|
-
for x in bin_range:
|
|
742
|
-
if x not in unique_range:
|
|
743
|
-
unique_range.append(x)
|
|
744
|
-
|
|
745
|
-
unique_range.sort()
|
|
746
|
-
|
|
747
|
-
return unique_range
|
|
773
|
+
left, right = _parse_bin_range_bounds(data, col=col)
|
|
774
|
+
return np.unique(np.concatenate([left, right])).tolist()
|
|
748
775
|
|
|
749
776
|
|
|
750
777
|
def chi2_auto_binning(df_pvt, max_bins, min_cnt_in_bin, p=0.95):
|
|
@@ -1165,9 +1192,8 @@ class Binning:
|
|
|
1165
1192
|
bin_num_col = self.bin_colnames[0]
|
|
1166
1193
|
bin_range_col = self.bin_colnames[1]
|
|
1167
1194
|
|
|
1168
|
-
self.data
|
|
1169
|
-
|
|
1170
|
-
lambda x: bin_range_list[int(x)] if self.include_missing else bin_range_list[int(x - 1)]
|
|
1195
|
+
self.data = _materialize_bin_columns(
|
|
1196
|
+
self.data, binned, bin_range_list, bin_num_col, bin_range_col
|
|
1171
1197
|
)
|
|
1172
1198
|
|
|
1173
1199
|
self.result = self.data
|
|
@@ -1237,9 +1263,8 @@ class Binning:
|
|
|
1237
1263
|
bin_num_col = self.bin_colnames[0]
|
|
1238
1264
|
bin_range_col = self.bin_colnames[1]
|
|
1239
1265
|
|
|
1240
|
-
self.data
|
|
1241
|
-
|
|
1242
|
-
lambda x: bin_range_list[int(x)] if self.include_missing else bin_range_list[int(x - 1)]
|
|
1266
|
+
self.data = _materialize_bin_columns(
|
|
1267
|
+
self.data, binned, bin_range_list, bin_num_col, bin_range_col
|
|
1243
1268
|
)
|
|
1244
1269
|
|
|
1245
1270
|
self.bin_edges = sorted([np.inf if str(x).lower() == 'inf' else -np.inf if str(x).lower() == '-inf' else x for x in bin_edges])
|
|
@@ -1385,10 +1410,9 @@ def chi2_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, t
|
|
|
1385
1410
|
binned = binning_series
|
|
1386
1411
|
rename_catlist = [i for i in range(1, len(bin_range_list) + 1)] if not include_missing else [i for i in range(0, len(bin_range_list))]
|
|
1387
1412
|
binned = binned.cat.rename_categories(rename_catlist)
|
|
1388
|
-
data
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
data[bin_range_col] = data[bin_num_col].apply(lambda x: bin_range_list[int(x)] if include_missing else bin_range_list[int(x - 1)])
|
|
1413
|
+
data = _materialize_bin_columns(
|
|
1414
|
+
data, binned, bin_range_list, bin_num_col, bin_range_col
|
|
1415
|
+
)
|
|
1392
1416
|
|
|
1393
1417
|
fnl_res = data
|
|
1394
1418
|
|
|
@@ -1399,7 +1423,7 @@ def chi2_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, t
|
|
|
1399
1423
|
|
|
1400
1424
|
def run_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, include_missing = True, equal_freq = True,
|
|
1401
1425
|
bin_colnames = ("bin_num", "bin_range"), ascending = False, right = True, include_lowest = False,
|
|
1402
|
-
tree_binning = False, target = None, random_state=42, spec_values = []):
|
|
1426
|
+
tree_binning = False, target = None, random_state=42, spec_values = [], fillna = -999999):
|
|
1403
1427
|
"""
|
|
1404
1428
|
通用分箱函数,支持等频或等距分箱。
|
|
1405
1429
|
|
|
@@ -1437,6 +1461,8 @@ def run_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, in
|
|
|
1437
1461
|
随机种子
|
|
1438
1462
|
spec_values : list, default []
|
|
1439
1463
|
特殊值列表
|
|
1464
|
+
fillna : scalar, default -999999
|
|
1465
|
+
`include_missing=True` 时用于承载缺失值的分箱哨兵。
|
|
1440
1466
|
|
|
1441
1467
|
Returns
|
|
1442
1468
|
-------
|
|
@@ -1481,7 +1507,8 @@ def run_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, in
|
|
|
1481
1507
|
ascending = ascending,
|
|
1482
1508
|
include_missing = include_missing,
|
|
1483
1509
|
random_state = random_state,
|
|
1484
|
-
spec_values = spec_values
|
|
1510
|
+
spec_values = spec_values,
|
|
1511
|
+
fillna = fillna)
|
|
1485
1512
|
|
|
1486
1513
|
left_sign='[' if include_lowest else '('
|
|
1487
1514
|
right_sign=']' if right else ')'
|
|
@@ -1489,8 +1516,9 @@ def run_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, in
|
|
|
1489
1516
|
|
|
1490
1517
|
rename_catlist = [i for i in range(1, len(bin_range_list) + 1)] if not include_missing else [i for i in range(0, len(bin_range_list))]
|
|
1491
1518
|
binned = binned.cat.rename_categories(rename_catlist)
|
|
1492
|
-
data
|
|
1493
|
-
|
|
1519
|
+
data = _materialize_bin_columns(
|
|
1520
|
+
data, binned, bin_range_list, bin_num_col, bin_range_col
|
|
1521
|
+
)
|
|
1494
1522
|
|
|
1495
1523
|
return data, bin_edges
|
|
1496
1524
|
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Binning_Tool.pyi
RENAMED
|
@@ -44,5 +44,5 @@ class Binning:
|
|
|
44
44
|
def run(self): ...
|
|
45
45
|
def get_result(self, return_edges = True): ...
|
|
46
46
|
def chi2_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, tgt_name = None, include_missing = True, equal_freq = True, bin_colnames = ('_bin_num', '_bin_range'), ascending = True, chi2_p = 0.95, init_equi_bins = 100, fillna = -999999, spec_values = [], init_points = None): ...
|
|
47
|
-
def run_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, include_missing = True, equal_freq = True, bin_colnames = ('bin_num', 'bin_range'), ascending = False, right = True, include_lowest = False, tree_binning = False, target = None, random_state = 42, spec_values = []): ...
|
|
47
|
+
def run_binning(data, column, nbins = 10, precision = 5, min_bin_prop = 0.05, include_missing = True, equal_freq = True, bin_colnames = ('bin_num', 'bin_range'), ascending = False, right = True, include_lowest = False, tree_binning = False, target = None, random_state = 42, spec_values = [], fillna = -999999): ...
|
|
48
48
|
def super_binning(data, score, dep, nbins = 10, precision = 5, min_bin_prop = 0.05, include_missing = True, equal_freq = True, chi2_method = False, chi2_p = 0.95, init_equi_bins = 2000, fillna = -999999, spec_values = [], tree_binning = False, random_state = 42, return_edges = False, ascending = True, bin_colnames = ('_bin_num', '_bin_range')): ...
|
|
@@ -1688,6 +1688,19 @@ def parse_sql_file(sql_path:str=None,
|
|
|
1688
1688
|
|
|
1689
1689
|
|
|
1690
1690
|
|
|
1691
|
+
def _calc_woe_iv_values(data, bad_pct, good_pct, fillwoe=True, filliv=True):
|
|
1692
|
+
"""Calculate WOE and IV together with one vectorized logarithm."""
|
|
1693
|
+
if len(data[bad_pct]) > 0 and len(data[good_pct]) > 0:
|
|
1694
|
+
bad_values = data[bad_pct]
|
|
1695
|
+
good_values = data[good_pct]
|
|
1696
|
+
woe = np.log(bad_values / good_values)
|
|
1697
|
+
iv = (bad_values - good_values) * woe
|
|
1698
|
+
else:
|
|
1699
|
+
woe = 0 if fillwoe else np.nan
|
|
1700
|
+
iv = 0 if filliv else np.nan
|
|
1701
|
+
return woe, iv
|
|
1702
|
+
|
|
1703
|
+
|
|
1691
1704
|
def calc_woe(data, bad_pct, good_pct, fillwoe=True):
|
|
1692
1705
|
"""
|
|
1693
1706
|
计算WOE(Weight of Evidence)值。
|
|
@@ -1716,15 +1729,7 @@ def calc_woe(data, bad_pct, good_pct, fillwoe=True):
|
|
|
1716
1729
|
>>> calc_woe(df, 'bad_pct', 'good_pct')
|
|
1717
1730
|
"""
|
|
1718
1731
|
|
|
1719
|
-
|
|
1720
|
-
woe = np.log(data[bad_pct] / data[good_pct])
|
|
1721
|
-
else:
|
|
1722
|
-
if fillwoe:
|
|
1723
|
-
woe = 0
|
|
1724
|
-
else:
|
|
1725
|
-
woe = np.nan
|
|
1726
|
-
|
|
1727
|
-
return woe
|
|
1732
|
+
return _calc_woe_iv_values(data, bad_pct, good_pct, fillwoe=fillwoe)[0]
|
|
1728
1733
|
|
|
1729
1734
|
|
|
1730
1735
|
def calc_iv(data, bad_pct, good_pct, filliv=True):
|
|
@@ -1755,15 +1760,7 @@ def calc_iv(data, bad_pct, good_pct, filliv=True):
|
|
|
1755
1760
|
>>> calc_iv(df, 'bad_pct', 'good_pct')
|
|
1756
1761
|
"""
|
|
1757
1762
|
|
|
1758
|
-
|
|
1759
|
-
iv = (data[bad_pct] - data[good_pct]) * np.log(data[bad_pct] / data[good_pct])
|
|
1760
|
-
else:
|
|
1761
|
-
if filliv:
|
|
1762
|
-
iv = 0
|
|
1763
|
-
else:
|
|
1764
|
-
iv = np.nan
|
|
1765
|
-
|
|
1766
|
-
return iv
|
|
1763
|
+
return _calc_woe_iv_values(data, bad_pct, good_pct, filliv=filliv)[1]
|
|
1767
1764
|
|
|
1768
1765
|
|
|
1769
1766
|
def save_model(model, filename):
|
|
@@ -2413,9 +2410,13 @@ class WOEIVCalculator:
|
|
|
2413
2410
|
-------
|
|
2414
2411
|
tuple
|
|
2415
2412
|
"""
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2413
|
+
return _calc_woe_iv_values(
|
|
2414
|
+
self.data,
|
|
2415
|
+
self.bad_pct_col,
|
|
2416
|
+
self.good_pct_col,
|
|
2417
|
+
fillwoe=fillna,
|
|
2418
|
+
filliv=fillna,
|
|
2419
|
+
)
|
|
2419
2420
|
|
|
2420
2421
|
|
|
2421
2422
|
def get_feature_names(model, model_type=None):
|
|
@@ -4,10 +4,10 @@ import numpy as np
|
|
|
4
4
|
import warnings
|
|
5
5
|
|
|
6
6
|
from .WOE_Plot_Tool import get_bivar_graph
|
|
7
|
-
from .WOE_Tool import mapping_woe, woe_transform
|
|
7
|
+
from .WOE_Tool import _vectorized_group_slopes, mapping_woe, woe_transform
|
|
8
8
|
|
|
9
9
|
from Modeling_Tool.Core.Binning_Tool import run_binning, get_bin_range_list
|
|
10
|
-
from Modeling_Tool.Core.utils import
|
|
10
|
+
from Modeling_Tool.Core.utils import _calc_woe_iv_values
|
|
11
11
|
from Modeling_Tool._utils.sentinels import SMF_MISSING_BIN
|
|
12
12
|
|
|
13
13
|
def get_overall_woe_table(woe_master, data, varlist=None):
|
|
@@ -29,8 +29,9 @@ def get_overall_woe_table(woe_master, data, varlist=None):
|
|
|
29
29
|
right = first_bin[-1] == ']'
|
|
30
30
|
|
|
31
31
|
fill_val = woe_master.missing_ref_value
|
|
32
|
-
data_proc = data.copy()
|
|
32
|
+
data_proc = data[[var, woe_master.dep]].copy()
|
|
33
33
|
data_proc[var] = data_proc[var].fillna(fill_val)
|
|
34
|
+
data_proc["_smf_good_n"] = data_proc[woe_master.dep].eq(0).astype(np.int64)
|
|
34
35
|
|
|
35
36
|
# 使用训练集边界分箱
|
|
36
37
|
binned, _ = run_binning(
|
|
@@ -54,14 +55,15 @@ def get_overall_woe_table(woe_master, data, varlist=None):
|
|
|
54
55
|
N=(var, "count"),
|
|
55
56
|
AVG_BAD=(dep, "mean"),
|
|
56
57
|
N_BAD=(dep, "sum"),
|
|
57
|
-
N_GOOD=(
|
|
58
|
+
N_GOOD=("_smf_good_n", "sum")
|
|
58
59
|
).reset_index()
|
|
59
60
|
|
|
60
61
|
# 计算 WOE / IV / LIFT
|
|
61
62
|
stats["BAD_PCT_PER_BIN"] = stats["N_BAD"] / stats["N_BAD"].sum()
|
|
62
63
|
stats["GOOD_PCT_PER_BIN"] = stats["N_GOOD"] / stats["N_GOOD"].sum()
|
|
63
|
-
stats["WOE"]
|
|
64
|
-
|
|
64
|
+
stats["WOE"], stats["IV"] = _calc_woe_iv_values(
|
|
65
|
+
stats, "BAD_PCT_PER_BIN", "GOOD_PCT_PER_BIN"
|
|
66
|
+
)
|
|
65
67
|
stats["LIFT"] = stats["AVG_BAD"] / stats["AVG_BAD"].mean()
|
|
66
68
|
stats["VAR"] = var
|
|
67
69
|
|
|
@@ -95,8 +97,9 @@ def get_group_woe_table(woe_master, data, group, varlist=None):
|
|
|
95
97
|
right = first_bin[-1] == ']'
|
|
96
98
|
fill_val = woe_master.missing_ref_value
|
|
97
99
|
|
|
98
|
-
data_proc = data.copy()
|
|
100
|
+
data_proc = data[[group, var, woe_master.dep]].copy()
|
|
99
101
|
data_proc[var] = data_proc[var].fillna(fill_val)
|
|
102
|
+
data_proc["_smf_good_n"] = data_proc[woe_master.dep].eq(0).astype(np.int64)
|
|
100
103
|
|
|
101
104
|
binned, _ = run_binning(
|
|
102
105
|
data=data_proc,
|
|
@@ -120,7 +123,7 @@ def get_group_woe_table(woe_master, data, group, varlist=None):
|
|
|
120
123
|
N=(var, "count"),
|
|
121
124
|
AVG_BAD=(dep, "mean"),
|
|
122
125
|
N_BAD=(dep, "sum"),
|
|
123
|
-
N_GOOD=(
|
|
126
|
+
N_GOOD=("_smf_good_n", "sum")
|
|
124
127
|
).reset_index()
|
|
125
128
|
|
|
126
129
|
# 计算各分箱内 WOE(全局分母)
|
|
@@ -128,8 +131,9 @@ def get_group_woe_table(woe_master, data, group, varlist=None):
|
|
|
128
131
|
total_good = stats["N_GOOD"].sum()
|
|
129
132
|
stats["BAD_PCT_PER_BIN"] = stats["N_BAD"] / total_bad
|
|
130
133
|
stats["GOOD_PCT_PER_BIN"] = stats["N_GOOD"] / total_good
|
|
131
|
-
stats["WOE"]
|
|
132
|
-
|
|
134
|
+
stats["WOE"], stats["IV"] = _calc_woe_iv_values(
|
|
135
|
+
stats, "BAD_PCT_PER_BIN", "GOOD_PCT_PER_BIN"
|
|
136
|
+
)
|
|
133
137
|
stats["LIFT"] = stats["AVG_BAD"] / stats["AVG_BAD"].mean()
|
|
134
138
|
stats["VAR"] = var
|
|
135
139
|
|
|
@@ -147,10 +151,12 @@ def get_group_woe_table(woe_master, data, group, varlist=None):
|
|
|
147
151
|
).reset_index()
|
|
148
152
|
|
|
149
153
|
# 计算单调性斜率(可选)
|
|
150
|
-
|
|
151
|
-
slopes = stats.groupby(group).apply(lambda x: calculate_slope_manual(x, "AVG_BAD"))
|
|
154
|
+
slopes = _vectorized_group_slopes(stats, group, "AVG_BAD")
|
|
152
155
|
sum_grp["SLOPE"] = sum_grp[group].map(slopes)
|
|
153
|
-
|
|
156
|
+
slope_values = sum_grp["SLOPE"].to_numpy()
|
|
157
|
+
sum_grp["direction"] = np.select(
|
|
158
|
+
[slope_values > 0, slope_values < 0], [1, -1], default=0
|
|
159
|
+
)
|
|
154
160
|
sum_grp["VAR"] = var
|
|
155
161
|
|
|
156
162
|
summaries.append(sum_grp)
|
|
@@ -364,7 +370,14 @@ class WOE_Master(object):
|
|
|
364
370
|
varlist = self.varlist
|
|
365
371
|
|
|
366
372
|
woe_mapping_table = self.get_mapping_table()
|
|
367
|
-
data_woe = mapping_woe(
|
|
373
|
+
data_woe = mapping_woe(
|
|
374
|
+
data,
|
|
375
|
+
varlist,
|
|
376
|
+
woe_mapping_table,
|
|
377
|
+
suffix=self.woe_suffix,
|
|
378
|
+
drop_bin_info=True,
|
|
379
|
+
missing_ref_value=self.missing_ref_value,
|
|
380
|
+
)
|
|
368
381
|
return data_woe
|
|
369
382
|
|
|
370
383
|
def update_woe(self, varlist, nbins=10, equal_freq=True, tree_binning_seed=None, chi2_config=None,
|
|
@@ -7,9 +7,53 @@ import numpy as np
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
import logging
|
|
9
9
|
|
|
10
|
-
from Modeling_Tool.Core.Binning_Tool import
|
|
10
|
+
from Modeling_Tool.Core.Binning_Tool import (
|
|
11
|
+
_parse_bin_range_bounds,
|
|
12
|
+
get_bin_range_list,
|
|
13
|
+
run_binning,
|
|
14
|
+
super_binning,
|
|
15
|
+
)
|
|
11
16
|
from Modeling_Tool.Core.Slope_Tool import calculate_slope_manual
|
|
12
|
-
from Modeling_Tool.Core.utils import calc_iv, calc_woe
|
|
17
|
+
from Modeling_Tool.Core.utils import _calc_woe_iv_values, calc_iv, calc_woe
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _vectorized_lookup(values, mapping_keys, mapping_values):
|
|
21
|
+
"""Map a whole Series through a unique lookup table with integer codes."""
|
|
22
|
+
key_index = pd.Index(np.asarray(list(mapping_keys), dtype=object))
|
|
23
|
+
if not key_index.is_unique:
|
|
24
|
+
raise ValueError("WOE mapping keys must be unique")
|
|
25
|
+
|
|
26
|
+
positions = key_index.get_indexer(values.astype(object).to_numpy())
|
|
27
|
+
output = np.full(len(values), np.nan, dtype=float)
|
|
28
|
+
valid = positions >= 0
|
|
29
|
+
if valid.any():
|
|
30
|
+
mapped = np.asarray(list(mapping_values), dtype=float)
|
|
31
|
+
output[valid] = np.take(mapped, positions[valid])
|
|
32
|
+
return pd.Series(output, index=values.index)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _vectorized_group_slopes(data, group_col, value_col):
|
|
36
|
+
"""Calculate per-group OLS slopes without ``groupby.apply`` callbacks."""
|
|
37
|
+
work = data[[group_col, value_col]].copy()
|
|
38
|
+
work["_smf_x"] = work.groupby(group_col, sort=False).cumcount().astype(float)
|
|
39
|
+
work["_smf_y"] = pd.to_numeric(work[value_col], errors="coerce")
|
|
40
|
+
work["_smf_xy"] = work["_smf_x"] * work["_smf_y"]
|
|
41
|
+
work["_smf_x2"] = work["_smf_x"] ** 2
|
|
42
|
+
|
|
43
|
+
grouped = work.groupby(group_col, sort=False).agg(
|
|
44
|
+
n=("_smf_y", "size"),
|
|
45
|
+
n_valid=("_smf_y", "count"),
|
|
46
|
+
sum_x=("_smf_x", "sum"),
|
|
47
|
+
sum_y=("_smf_y", "sum"),
|
|
48
|
+
sum_xy=("_smf_xy", "sum"),
|
|
49
|
+
sum_x2=("_smf_x2", "sum"),
|
|
50
|
+
)
|
|
51
|
+
numerator = grouped["n"] * grouped["sum_xy"] - grouped["sum_x"] * grouped["sum_y"]
|
|
52
|
+
denominator = grouped["n"] * grouped["sum_x2"] - grouped["sum_x"] ** 2
|
|
53
|
+
slopes = numerator / denominator
|
|
54
|
+
slopes[(grouped["n"] != grouped["n_valid"]) | denominator.eq(0)] = np.nan
|
|
55
|
+
slopes.name = "SLOPE"
|
|
56
|
+
return slopes
|
|
13
57
|
|
|
14
58
|
def is_monotonic(data, column, direction='auto', strict=False, handle_nan='drop'):
|
|
15
59
|
"""检查Pandas Series或DataFrame列是否单调(递增或递减)。
|
|
@@ -216,24 +260,33 @@ class WOETransformer:
|
|
|
216
260
|
tuple
|
|
217
261
|
(woe_table, woe_mapping_dict) 元组
|
|
218
262
|
"""
|
|
219
|
-
|
|
220
|
-
|
|
263
|
+
working = binning_res.copy()
|
|
264
|
+
target = working[dep]
|
|
265
|
+
working["_smf_target_n"] = target.notna().astype(np.int64)
|
|
266
|
+
working["_smf_bad_n"] = target.eq(1).astype(np.int64)
|
|
267
|
+
working["_smf_good_n"] = target.eq(0).astype(np.int64)
|
|
268
|
+
woe_table = working.groupby(
|
|
269
|
+
[f"_bin_num_{var}", f"_bin_range_{var}"], dropna=False
|
|
270
|
+
).agg(
|
|
221
271
|
MIN=(var, "min"),
|
|
222
272
|
MAX=(var, "max"),
|
|
223
273
|
N=(f"_bin_num_{var}", "count"),
|
|
224
274
|
AVG_SCORE=(var, "mean"),
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
N_GOOD=(dep, lambda x: (x == 0).sum())
|
|
275
|
+
TARGET_N=("_smf_target_n", "sum"),
|
|
276
|
+
N_BAD=("_smf_bad_n", "sum"),
|
|
277
|
+
N_GOOD=("_smf_good_n", "sum"),
|
|
229
278
|
)
|
|
279
|
+
woe_table["AVG_BAD"] = woe_table["N_BAD"] / woe_table["TARGET_N"]
|
|
280
|
+
woe_table["AVG_GOOD"] = woe_table["N_GOOD"] / woe_table["TARGET_N"]
|
|
281
|
+
woe_table = woe_table.drop(columns="TARGET_N")
|
|
230
282
|
|
|
231
283
|
# IV/WOE Calculation
|
|
232
284
|
woe_table["BAD_PCT_PER_BIN"] = woe_table["N_BAD"] / woe_table["N_BAD"].sum()
|
|
233
285
|
woe_table["GOOD_PCT_PER_BIN"] = woe_table["N_GOOD"] / woe_table["N_GOOD"].sum()
|
|
234
286
|
woe_table["LIFT"] = woe_table['AVG_BAD'] / woe_table['AVG_BAD'].mean()
|
|
235
|
-
woe_table["WOE"]
|
|
236
|
-
|
|
287
|
+
woe_table["WOE"], woe_table["IV"] = _calc_woe_iv_values(
|
|
288
|
+
woe_table, "BAD_PCT_PER_BIN", "GOOD_PCT_PER_BIN"
|
|
289
|
+
)
|
|
237
290
|
|
|
238
291
|
# WOE Mapping Dictionary
|
|
239
292
|
woe_table = woe_table.reset_index(drop=False)
|
|
@@ -300,7 +353,11 @@ class WOETransformer:
|
|
|
300
353
|
logging.warning(f"WARNING: {var} WOE values are NOT monotonic in Train Dataset!")
|
|
301
354
|
|
|
302
355
|
# WOE Mapping to DataFrame
|
|
303
|
-
train_res[f"{var}_woe"] =
|
|
356
|
+
train_res[f"{var}_woe"] = _vectorized_lookup(
|
|
357
|
+
train_res[f"_bin_range_{var}"],
|
|
358
|
+
train_woe_mapping_dict.keys(),
|
|
359
|
+
train_woe_mapping_dict.values(),
|
|
360
|
+
)
|
|
304
361
|
|
|
305
362
|
# Drop Bin Info
|
|
306
363
|
if self.drop_bin_info:
|
|
@@ -312,7 +369,10 @@ class WOETransformer:
|
|
|
312
369
|
woe_mapping_table["BIN_NUM"] = woe_mapping_table[f"_bin_num_{var}"]
|
|
313
370
|
woe_mapping_table["VAR"] = var
|
|
314
371
|
oot_res = _mapping_woe_single_var(
|
|
315
|
-
data=oot_df,
|
|
372
|
+
data=oot_df,
|
|
373
|
+
var=var,
|
|
374
|
+
woe_mapping_table=woe_mapping_table,
|
|
375
|
+
missing_ref_value=self.fillna,
|
|
316
376
|
)
|
|
317
377
|
|
|
318
378
|
if self.ret_woe_table and oot_df is not None:
|
|
@@ -426,24 +486,12 @@ def convert_single_var_woe(data, var, woe_mapping_table, missing_ref=None, ret_b
|
|
|
426
486
|
var_woe_mapping = woe_mapping_table.query(f"var_name == '{var}_woe'")
|
|
427
487
|
var_woe_mapping = var_woe_mapping[["bin_no", "bin_value", "woe", "n"]]
|
|
428
488
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
)
|
|
432
|
-
|
|
433
|
-
woe_mapping_dict = dict(zip(var_woe_mapping['bin_no'], var_woe_mapping['woe']))
|
|
434
|
-
bin_range = [
|
|
435
|
-
float(v.strip()) if v.strip() != 'inf' else np.inf
|
|
436
|
-
for x in var_woe_mapping["bin_value_list"].tolist()
|
|
437
|
-
for v in x
|
|
438
|
-
]
|
|
439
|
-
|
|
440
|
-
unique_range = []
|
|
441
|
-
for x in bin_range:
|
|
442
|
-
if x not in unique_range:
|
|
443
|
-
unique_range.append(x)
|
|
489
|
+
left, right = _parse_bin_range_bounds(var_woe_mapping, col="bin_value")
|
|
490
|
+
unique_range = np.unique(np.concatenate([left, right])).tolist()
|
|
444
491
|
|
|
445
|
-
|
|
446
|
-
|
|
492
|
+
var_serires = data[var]
|
|
493
|
+
if missing_ref is not None:
|
|
494
|
+
var_serires = var_serires.fillna(missing_ref)
|
|
447
495
|
|
|
448
496
|
bin_no_transform = pd.cut(
|
|
449
497
|
var_serires,
|
|
@@ -455,9 +503,11 @@ def convert_single_var_woe(data, var, woe_mapping_table, missing_ref=None, ret_b
|
|
|
455
503
|
if ret_bin_no:
|
|
456
504
|
return bin_no_transform
|
|
457
505
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
506
|
+
return _vectorized_lookup(
|
|
507
|
+
pd.Series(bin_no_transform.astype(object), index=data.index),
|
|
508
|
+
var_woe_mapping["bin_no"],
|
|
509
|
+
var_woe_mapping["woe"],
|
|
510
|
+
)
|
|
461
511
|
|
|
462
512
|
|
|
463
513
|
class WOEMappingTransformer:
|
|
@@ -727,16 +777,14 @@ def get_woe_table(data, var, dep, grp_name=None, nbins=10, precision=5,
|
|
|
727
777
|
direction = 1 if dep_slope > 0 else -1 if dep_slope < 0 else 0
|
|
728
778
|
|
|
729
779
|
if grp_name:
|
|
730
|
-
slope_grp =
|
|
731
|
-
gains_table.groupby([grp_name]).apply(calculate_slope_manual, "AVG_BAD"),
|
|
732
|
-
columns=["SLOPE"]
|
|
733
|
-
)
|
|
780
|
+
slope_grp = _vectorized_group_slopes(gains_table, grp_name, "AVG_BAD").to_frame()
|
|
734
781
|
grp_summary = gains_table.groupby([grp_name]).agg(
|
|
735
782
|
N=("N", sum), IV=("IV", sum), KS=("KS_PER_BIN", max),
|
|
736
783
|
BTM_LIFT=("LIFT", min), TOP_LIFT=("LIFT", max)
|
|
737
784
|
).merge(slope_grp, left_index=True, right_index=True)
|
|
738
|
-
|
|
739
|
-
|
|
785
|
+
slope_values = grp_summary["SLOPE"].to_numpy()
|
|
786
|
+
grp_summary['direction'] = np.select(
|
|
787
|
+
[slope_values > 0, slope_values < 0], [1, -1], default=0
|
|
740
788
|
)
|
|
741
789
|
grp_woe_pvt = gains_table.pivot_table(
|
|
742
790
|
index=["BIN_NUM", "BIN_RANGE"],
|
|
@@ -969,7 +1017,58 @@ def woe_transformation(train_df, varlist, dep, oot_df=None, nbins=10, chi2_confi
|
|
|
969
1017
|
return transformer.transform(train_df, varlist, dep, oot_df)
|
|
970
1018
|
|
|
971
1019
|
|
|
972
|
-
def
|
|
1020
|
+
def _map_woe_arrays(data, var, woe_mapping_table, suffix="_woe", missing_ref_value=-999999):
|
|
1021
|
+
"""Return vectorized WOE and bin columns for one feature."""
|
|
1022
|
+
var_woe_mapping = woe_mapping_table.loc[
|
|
1023
|
+
woe_mapping_table["VAR"].eq(var), ["BIN_NUM", "BIN_RANGE", "WOE", "N"]
|
|
1024
|
+
].copy()
|
|
1025
|
+
if var_woe_mapping.empty:
|
|
1026
|
+
raise KeyError(f"No WOE mapping rows found for variable {var!r}")
|
|
1027
|
+
|
|
1028
|
+
first_range = var_woe_mapping["BIN_RANGE"].astype("string").dropna().iloc[0]
|
|
1029
|
+
include_lowest = first_range.startswith("[")
|
|
1030
|
+
right = first_range.endswith("]")
|
|
1031
|
+
bin_range = get_bin_range_list(var_woe_mapping, col="BIN_RANGE")
|
|
1032
|
+
|
|
1033
|
+
binned, _ = run_binning(
|
|
1034
|
+
data=data[[var]].copy(),
|
|
1035
|
+
column=var,
|
|
1036
|
+
nbins=sorted(set([*bin_range, -np.inf, np.inf])),
|
|
1037
|
+
include_missing=True,
|
|
1038
|
+
equal_freq=True,
|
|
1039
|
+
bin_colnames=("_BIN_NUM_", "_BIN_RANGE_"),
|
|
1040
|
+
ascending=True,
|
|
1041
|
+
include_lowest=include_lowest,
|
|
1042
|
+
right=right,
|
|
1043
|
+
fillna=missing_ref_value,
|
|
1044
|
+
)
|
|
1045
|
+
woe_values = _vectorized_lookup(
|
|
1046
|
+
binned["_BIN_RANGE_"],
|
|
1047
|
+
var_woe_mapping["BIN_RANGE"],
|
|
1048
|
+
var_woe_mapping["WOE"],
|
|
1049
|
+
)
|
|
1050
|
+
missing_count = int(woe_values.isna().sum())
|
|
1051
|
+
if missing_count:
|
|
1052
|
+
logging.warning(f"WARNING: Failed to Map WOE values for {missing_count} Records!")
|
|
1053
|
+
|
|
1054
|
+
return pd.DataFrame(
|
|
1055
|
+
{
|
|
1056
|
+
"_BIN_NUM_": binned["_BIN_NUM_"].to_numpy(copy=False),
|
|
1057
|
+
"_BIN_RANGE_": binned["_BIN_RANGE_"].to_numpy(copy=False),
|
|
1058
|
+
f"{var}{suffix}": woe_values.to_numpy(copy=False),
|
|
1059
|
+
},
|
|
1060
|
+
index=data.index,
|
|
1061
|
+
)
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
def _mapping_woe_single_var(
|
|
1065
|
+
data,
|
|
1066
|
+
var,
|
|
1067
|
+
woe_mapping_table,
|
|
1068
|
+
suffix="_woe",
|
|
1069
|
+
drop_bin_info=True,
|
|
1070
|
+
missing_ref_value=-999999,
|
|
1071
|
+
):
|
|
973
1072
|
"""基于WOE映射表为单个变量映射WOE值。
|
|
974
1073
|
|
|
975
1074
|
使用预计算的WOE映射表对新数据进行转换,
|
|
@@ -987,6 +1086,9 @@ def _mapping_woe_single_var(data, var, woe_mapping_table, suffix="_woe", drop_bi
|
|
|
987
1086
|
变量名后缀,默认为'_woe'
|
|
988
1087
|
drop_bin_info : bool, optional
|
|
989
1088
|
是否删除中间分箱信息列,默认为True
|
|
1089
|
+
missing_ref_value : scalar, optional
|
|
1090
|
+
转换缺失值时使用的训练期分箱哨兵,默认 -999999。若训练使用了
|
|
1091
|
+
自定义哨兵,转换时必须传入同一个值。
|
|
990
1092
|
|
|
991
1093
|
返回:
|
|
992
1094
|
--------
|
|
@@ -1000,62 +1102,29 @@ def _mapping_woe_single_var(data, var, woe_mapping_table, suffix="_woe", drop_bi
|
|
|
1000
1102
|
# from Modeling_Tool.Modeling_Tool.Model_Eval_Tool import run_binning
|
|
1001
1103
|
# from 代码优化.Model_Eval_Tool import get_bin_range_list
|
|
1002
1104
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
var_woe_mapping = woe_mapping_table.query(f"VAR == '{var}'")
|
|
1010
|
-
var_woe_mapping = var_woe_mapping[["BIN_NUM", "BIN_RANGE", "WOE", "N"]]
|
|
1011
|
-
bin_range = get_bin_range_list(var_woe_mapping, col="BIN_RANGE")
|
|
1012
|
-
woe_mapping_dict = dict(zip(var_woe_mapping['BIN_RANGE'], var_woe_mapping['WOE']))
|
|
1013
|
-
|
|
1014
|
-
res, edges = run_binning(
|
|
1015
|
-
data=data,
|
|
1016
|
-
column=var,
|
|
1017
|
-
nbins=sorted(set(list(bin_range) + [-np.inf, np.inf])),
|
|
1018
|
-
include_missing=True,
|
|
1019
|
-
equal_freq=True,
|
|
1020
|
-
bin_colnames=(f"_BIN_NUM_", f"_BIN_RANGE_"),
|
|
1021
|
-
ascending=True,
|
|
1022
|
-
include_lowest=include_lowest,
|
|
1023
|
-
right=right
|
|
1024
|
-
)
|
|
1025
|
-
|
|
1026
|
-
res[f"{var}{suffix}"] = res["_BIN_RANGE_"].map(woe_mapping_dict)
|
|
1027
|
-
|
|
1028
|
-
res_woe_table = res.groupby(["_BIN_RANGE_"]).agg(
|
|
1029
|
-
{f"_BIN_RANGE_": "count", var: [min, max], f"{var}{suffix}": [min, max, "mean"]}
|
|
1030
|
-
)
|
|
1031
|
-
|
|
1032
|
-
check_res = res_woe_table.dropna()
|
|
1033
|
-
assert (check_res[(f"{var}{suffix}", "min")] == check_res[(f"{var}{suffix}", "max")]).all(), \
|
|
1034
|
-
f"Error occurred when mapping var: {var}{suffix}"
|
|
1035
|
-
assert data.shape[0] == res.shape[0]
|
|
1036
|
-
|
|
1037
|
-
missing_woe = pd.isnull(res[var + suffix]).sum() > 0
|
|
1038
|
-
if missing_woe:
|
|
1039
|
-
logging.warning(f"WARNING: Failed to Map WOE values for {pd.isnull(res[var + suffix]).sum()} Records!")
|
|
1040
|
-
|
|
1041
|
-
woe = pd.DataFrame(
|
|
1042
|
-
res_woe_table.loc[
|
|
1043
|
-
res_woe_table[(var, "min")] != res_woe_table[(var, "max")],
|
|
1044
|
-
(f"{var}_woe", "mean")
|
|
1045
|
-
]
|
|
1105
|
+
mapped = _map_woe_arrays(
|
|
1106
|
+
data,
|
|
1107
|
+
var,
|
|
1108
|
+
woe_mapping_table,
|
|
1109
|
+
suffix=suffix,
|
|
1110
|
+
missing_ref_value=missing_ref_value,
|
|
1046
1111
|
)
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1112
|
+
mapped_cols = [f"{var}{suffix}"]
|
|
1113
|
+
if not drop_bin_info:
|
|
1114
|
+
mapped_cols = ["_BIN_NUM_", "_BIN_RANGE_", *mapped_cols]
|
|
1115
|
+
|
|
1116
|
+
base = data.drop(columns=mapped_cols, errors="ignore")
|
|
1117
|
+
return pd.concat([base, mapped[mapped_cols]], axis=1)
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
def mapping_woe(
|
|
1121
|
+
data,
|
|
1122
|
+
varlist,
|
|
1123
|
+
woe_mapping_table,
|
|
1124
|
+
suffix="_woe",
|
|
1125
|
+
drop_bin_info=True,
|
|
1126
|
+
missing_ref_value=-999999,
|
|
1127
|
+
):
|
|
1059
1128
|
"""基于WOE映射表批量映射WOE值。
|
|
1060
1129
|
|
|
1061
1130
|
使用预计算的WOE映射表对多个变量进行WOE转换。
|
|
@@ -1072,6 +1141,9 @@ def mapping_woe(data, varlist, woe_mapping_table, suffix="_woe", drop_bin_info =
|
|
|
1072
1141
|
变量名后缀,默认为'_woe'
|
|
1073
1142
|
drop_bin_info : bool, optional
|
|
1074
1143
|
是否删除中间分箱信息列,默认为True
|
|
1144
|
+
missing_ref_value : scalar, optional
|
|
1145
|
+
转换缺失值时使用的训练期分箱哨兵,默认 -999999。若训练使用了
|
|
1146
|
+
自定义哨兵,转换时必须传入同一个值。
|
|
1075
1147
|
|
|
1076
1148
|
返回:
|
|
1077
1149
|
--------
|
|
@@ -1082,13 +1154,27 @@ def mapping_woe(data, varlist, woe_mapping_table, suffix="_woe", drop_bin_info =
|
|
|
1082
1154
|
--------
|
|
1083
1155
|
>>> result = mapping_woe(df, ['var1', 'var2'], woe_table)
|
|
1084
1156
|
"""
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
suffix=suffix
|
|
1088
|
-
# drop_bin_info=drop_bin_info
|
|
1089
|
-
)
|
|
1090
|
-
res = data.copy()
|
|
1157
|
+
woe_columns = {}
|
|
1158
|
+
last_bin_columns = None
|
|
1091
1159
|
for var in varlist:
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1160
|
+
mapped = _map_woe_arrays(
|
|
1161
|
+
data,
|
|
1162
|
+
var,
|
|
1163
|
+
woe_mapping_table,
|
|
1164
|
+
suffix=suffix,
|
|
1165
|
+
missing_ref_value=missing_ref_value,
|
|
1166
|
+
)
|
|
1167
|
+
woe_columns[f"{var}{suffix}"] = mapped[f"{var}{suffix}"].to_numpy(copy=False)
|
|
1168
|
+
last_bin_columns = mapped[["_BIN_NUM_", "_BIN_RANGE_"]]
|
|
1169
|
+
|
|
1170
|
+
output_cols = list(woe_columns)
|
|
1171
|
+
if not drop_bin_info:
|
|
1172
|
+
output_cols.extend(["_BIN_NUM_", "_BIN_RANGE_"])
|
|
1173
|
+
base = data.drop(columns=output_cols, errors="ignore").copy()
|
|
1174
|
+
|
|
1175
|
+
frames = [base]
|
|
1176
|
+
if not drop_bin_info and last_bin_columns is not None:
|
|
1177
|
+
frames.append(last_bin_columns)
|
|
1178
|
+
if woe_columns:
|
|
1179
|
+
frames.append(pd.DataFrame(woe_columns, index=data.index))
|
|
1180
|
+
return pd.concat(frames, axis=1)
|
|
@@ -38,4 +38,4 @@ def get_woe_table(data, var, dep, grp_name = None, nbins = 10, precision = 5, mi
|
|
|
38
38
|
def plot_monotonicity_check(data, column, title = None, include_missing = True): ...
|
|
39
39
|
def woe_transform(train_df, var, dep, nbins, oot_df = None, chi2_config = None, tree_binning_seed = None, precision = 5, min_bin_prop = 0.05, include_missing = False, equal_freq = True, ascending = True, fillna = -999999, spec_values = None, drop_bin_info = True, ret_woe_table = True, check_monotonicity = False): ...
|
|
40
40
|
def woe_transformation(train_df, varlist, dep, oot_df = None, nbins = 10, chi2_config = None, tree_binning_seed = None, precision = 5, min_bin_prop = 0.05, include_missing = False, equal_freq = True, fillna = -999999, spec_values = None, drop_bin_info = True, ret_woe_table = True): ...
|
|
41
|
-
def mapping_woe(data, varlist, woe_mapping_table, suffix = '_woe', drop_bin_info = True): ...
|
|
41
|
+
def mapping_woe(data, varlist, woe_mapping_table, suffix = '_woe', drop_bin_info = True, missing_ref_value = -999999): ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SuperModelingFactory
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.10
|
|
4
4
|
Summary: Credit risk modeling factory: WOE binning, scorecards, LightGBM, Excel reporting.
|
|
5
5
|
Home-page: https://github.com/Kyle-J-Sun/SuperModelingFactory
|
|
6
6
|
Author: Kyle Sun
|
|
@@ -265,7 +265,7 @@ em.close_workbook()
|
|
|
265
265
|
|
|
266
266
|
## 版本
|
|
267
267
|
|
|
268
|
-
- **Version**: 0.5.
|
|
268
|
+
- **Version**: 0.5.10
|
|
269
269
|
- **Author**: Jingkai Sun
|
|
270
270
|
|
|
271
271
|
## 许可证
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SuperModelingFactory
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.10
|
|
4
4
|
Summary: Credit risk modeling factory: WOE binning, scorecards, LightGBM, Excel reporting.
|
|
5
5
|
Home-page: https://github.com/Kyle-J-Sun/SuperModelingFactory
|
|
6
6
|
Author: Kyle Sun
|
|
@@ -265,7 +265,7 @@ em.close_workbook()
|
|
|
265
265
|
|
|
266
266
|
## 版本
|
|
267
267
|
|
|
268
|
-
- **Version**: 0.5.
|
|
268
|
+
- **Version**: 0.5.10
|
|
269
269
|
- **Author**: Jingkai Sun
|
|
270
270
|
|
|
271
271
|
## 许可证
|
|
@@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"
|
|
|
12
12
|
|
|
13
13
|
[project]
|
|
14
14
|
name = "SuperModelingFactory"
|
|
15
|
-
version = "0.5.
|
|
15
|
+
version = "0.5.10"
|
|
16
16
|
description = "Credit risk modeling factory: WOE binning, scorecards, LightGBM, Excel reporting."
|
|
17
17
|
readme = "README.md"
|
|
18
18
|
requires-python = ">=3.10"
|
|
@@ -15,7 +15,7 @@ def _read(path: str) -> str:
|
|
|
15
15
|
|
|
16
16
|
setup(
|
|
17
17
|
name="SuperModelingFactory",
|
|
18
|
-
version=os.environ.get("SMF_VERSION", "0.5.
|
|
18
|
+
version=os.environ.get("SMF_VERSION", "0.5.10"),
|
|
19
19
|
description="Credit risk modeling factory: WOE binning, scorecards, LightGBM, Excel reporting.",
|
|
20
20
|
long_description=_read("README.md"),
|
|
21
21
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Json_Data_Converter.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Model_Registry_Tool.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Parallel_Engine.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Proc_Compare.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/Slope_Tool.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/XOR_Encryptor.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/XOR_Encryptor.pyi
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/kDataFrame.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Core/sample_weight_utils.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Evaluation_Tool.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Evaluation_Tool.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Model_Eval_Tool.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/Model_Eval_Tool.pyi
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/evaluate_model.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/evaluate_model.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Eval/weighted_eval_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Explainability/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Feature_Insights.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Feature_Screen.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/PSI_Tool.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/PSI_Tool.pyi
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/Weighted_Screen.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Feature/__init__.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/Backward_Tool.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/Backward_Tool.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Model/GBM_Search_Tool.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/__init__.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/_common.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/credit_model.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/field_meta.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/mock_sample.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/orchestrator.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Pipeline/sample_analysis.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Reject_Infer.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Reject_Infer.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Sample_Split.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/Sample/Sample_Split.pyi
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Adapter.pyi
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Monotone_Binner.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Monotone_Binner.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Plot_Tool.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Plot_Tool.pyi
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Report_Builder.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/WOE_Report_Builder.pyi
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/plot_woe_tool.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/WOE/plot_woe_tool.pyi
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/_utils/nan_guard.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/_utils/sentinels.py
RENAMED
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/ref_font/WeiRuanYaHei.ttf
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/ref_font/__init__.py
RENAMED
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/Modeling_Tool/ref_font/simsun.ttc
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supermodelingfactory-0.5.9 → supermodelingfactory-0.5.10}/SuperModelingFactory.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|