SuperModelingFactory 0.2.0__py3-none-any.whl

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.
Files changed (79) hide show
  1. ExcelMaster/ExcelFormatTool.py +487 -0
  2. ExcelMaster/ExcelMaster.py +917 -0
  3. ExcelMaster/Template.py +525 -0
  4. ExcelMaster/Utility.py +233 -0
  5. ExcelMaster/__init__.py +3 -0
  6. Modeling_Tool/Core/Binning_Tool.py +1608 -0
  7. Modeling_Tool/Core/Binning_Tool.pyi +48 -0
  8. Modeling_Tool/Core/Check_DuckDB_Compatibility.py +835 -0
  9. Modeling_Tool/Core/Json_Data_Converter.py +621 -0
  10. Modeling_Tool/Core/Model_Registry_Tool.py +199 -0
  11. Modeling_Tool/Core/ODPS_Tool.py +284 -0
  12. Modeling_Tool/Core/Slope_Tool.py +356 -0
  13. Modeling_Tool/Core/Slope_Tool.pyi +31 -0
  14. Modeling_Tool/Core/XOR_Encryptor.py +207 -0
  15. Modeling_Tool/Core/XOR_Encryptor.pyi +26 -0
  16. Modeling_Tool/Core/__init__.py +99 -0
  17. Modeling_Tool/Core/kDataFrame.py +228 -0
  18. Modeling_Tool/Core/kDataFrame.pyi +43 -0
  19. Modeling_Tool/Core/sample_weight_utils.py +77 -0
  20. Modeling_Tool/Core/utils.py +2672 -0
  21. Modeling_Tool/Eval/Evaluation_Tool.py +1452 -0
  22. Modeling_Tool/Eval/Evaluation_Tool.pyi +47 -0
  23. Modeling_Tool/Eval/Model_Eval_Tool.py +2548 -0
  24. Modeling_Tool/Eval/Model_Eval_Tool.pyi +37 -0
  25. Modeling_Tool/Eval/__init__.py +54 -0
  26. Modeling_Tool/Eval/evaluate_model.py +2008 -0
  27. Modeling_Tool/Eval/evaluate_model.pyi +50 -0
  28. Modeling_Tool/Eval/weighted_eval_utils.py +326 -0
  29. Modeling_Tool/Explainability/Coalition_Structure.py +305 -0
  30. Modeling_Tool/Explainability/Model_Explainer.py +743 -0
  31. Modeling_Tool/Explainability/__init__.py +24 -0
  32. Modeling_Tool/Feature/Distribution_Tool.py +509 -0
  33. Modeling_Tool/Feature/Distribution_Tool.pyi +42 -0
  34. Modeling_Tool/Feature/Feature_Insights.py +762 -0
  35. Modeling_Tool/Feature/Feature_Insights.pyi +33 -0
  36. Modeling_Tool/Feature/PSI_Tool.py +1195 -0
  37. Modeling_Tool/Feature/PSI_Tool.pyi +29 -0
  38. Modeling_Tool/Feature/WOE_Engine_Feature_Patch.py +355 -0
  39. Modeling_Tool/Feature/__init__.py +40 -0
  40. Modeling_Tool/Model/Backward_Tool.py +778 -0
  41. Modeling_Tool/Model/Backward_Tool.pyi +45 -0
  42. Modeling_Tool/Model/GBM_Search_Tool.py +251 -0
  43. Modeling_Tool/Model/GBM_Tool.py +1610 -0
  44. Modeling_Tool/Model/GBM_Tool.pyi +90 -0
  45. Modeling_Tool/Model/LRM_Tool.py +1198 -0
  46. Modeling_Tool/Model/LRM_Tool.pyi +47 -0
  47. Modeling_Tool/Model/__init__.py +61 -0
  48. Modeling_Tool/Sample/Distribution_Adaptation.py +131 -0
  49. Modeling_Tool/Sample/Distribution_Adaptation.pyi +30 -0
  50. Modeling_Tool/Sample/Reject_Infer.py +413 -0
  51. Modeling_Tool/Sample/Reject_Infer.pyi +43 -0
  52. Modeling_Tool/Sample/Sample_Split.py +520 -0
  53. Modeling_Tool/Sample/Sample_Split.pyi +43 -0
  54. Modeling_Tool/Sample/__init__.py +31 -0
  55. Modeling_Tool/UAT/UAT_Consistency_Checker.py +1180 -0
  56. Modeling_Tool/UAT/__init__.py +19 -0
  57. Modeling_Tool/WOE/WOE_Adapter.py +204 -0
  58. Modeling_Tool/WOE/WOE_Adapter.pyi +21 -0
  59. Modeling_Tool/WOE/WOE_Master.py +491 -0
  60. Modeling_Tool/WOE/WOE_Master.pyi +40 -0
  61. Modeling_Tool/WOE/WOE_Monotone_Binner.py +3324 -0
  62. Modeling_Tool/WOE/WOE_Monotone_Binner.pyi +71 -0
  63. Modeling_Tool/WOE/WOE_Plot_Tool.py +919 -0
  64. Modeling_Tool/WOE/WOE_Plot_Tool.pyi +46 -0
  65. Modeling_Tool/WOE/WOE_Report_Builder.py +214 -0
  66. Modeling_Tool/WOE/WOE_Report_Builder.pyi +24 -0
  67. Modeling_Tool/WOE/WOE_Tool.py +1094 -0
  68. Modeling_Tool/WOE/WOE_Tool.pyi +41 -0
  69. Modeling_Tool/WOE/__init__.py +86 -0
  70. Modeling_Tool/WOE/plot_woe_tool.py +290 -0
  71. Modeling_Tool/WOE/plot_woe_tool.pyi +25 -0
  72. Modeling_Tool/__init__.py +176 -0
  73. Report/Report_Tool.py +380 -0
  74. Report/__init__.py +3 -0
  75. supermodelingfactory-0.2.0.dist-info/METADATA +268 -0
  76. supermodelingfactory-0.2.0.dist-info/RECORD +79 -0
  77. supermodelingfactory-0.2.0.dist-info/WHEEL +5 -0
  78. supermodelingfactory-0.2.0.dist-info/licenses/LICENSE +102 -0
  79. supermodelingfactory-0.2.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,491 @@
1
+ import os
2
+ import pandas as pd
3
+ import numpy as np
4
+
5
+ from .WOE_Plot_Tool import get_bivar_graph
6
+ from .WOE_Tool import mapping_woe, woe_transform
7
+
8
+ from Modeling_Tool.Core.Binning_Tool import run_binning, get_bin_range_list
9
+ from Modeling_Tool.Core.utils import calc_woe, calc_iv
10
+
11
+ def get_overall_woe_table(woe_master, data, varlist=None):
12
+ """生成整体样本的WOE统计表,结构对齐训练集映射表。"""
13
+ if varlist is None:
14
+ varlist = woe_master.varlist
15
+
16
+ all_tables = []
17
+ for var in varlist:
18
+ var_map = woe_master.woe_dict[var]
19
+
20
+ # 提取分箱边界并保留 inf
21
+ edges = get_bin_range_list(var_map, col="BIN_RANGE")
22
+ custom_edges = sorted(set(list(edges) + [-np.inf, np.inf]))
23
+
24
+ # 从训练集 BIN_RANGE 推断闭合方式
25
+ first_bin = var_map["BIN_RANGE"].dropna().iloc[0]
26
+ include_lowest = first_bin[0] == '['
27
+ right = first_bin[-1] == ']'
28
+
29
+ fill_val = woe_master.missing_ref_value
30
+ data_proc = data.copy()
31
+ data_proc[var] = data_proc[var].fillna(fill_val)
32
+
33
+ # 使用训练集边界分箱
34
+ binned, _ = run_binning(
35
+ data=data_proc,
36
+ column=var,
37
+ nbins=custom_edges,
38
+ include_missing=True,
39
+ equal_freq=False,
40
+ bin_colnames=("_BIN_NUM", "_BIN_RANGE"),
41
+ ascending=True,
42
+ include_lowest=include_lowest,
43
+ right=right,
44
+ spec_values=[fill_val]
45
+ )
46
+
47
+ dep = woe_master.dep
48
+ grp = binned.groupby(["_BIN_NUM", "_BIN_RANGE"], dropna=False)
49
+ stats = grp.agg(
50
+ MIN=(var, "min"),
51
+ MAX=(var, "max"),
52
+ N=(var, "count"),
53
+ AVG_BAD=(dep, "mean"),
54
+ N_BAD=(dep, "sum"),
55
+ N_GOOD=(dep, lambda x: (x == 0).sum())
56
+ ).reset_index()
57
+
58
+ # 计算 WOE / IV / LIFT
59
+ stats["BAD_PCT_PER_BIN"] = stats["N_BAD"] / stats["N_BAD"].sum()
60
+ stats["GOOD_PCT_PER_BIN"] = stats["N_GOOD"] / stats["N_GOOD"].sum()
61
+ stats["WOE"] = calc_woe(stats, bad_pct="BAD_PCT_PER_BIN", good_pct="GOOD_PCT_PER_BIN")
62
+ stats["IV"] = calc_iv(stats, bad_pct="BAD_PCT_PER_BIN", good_pct="GOOD_PCT_PER_BIN")
63
+ stats["LIFT"] = stats["AVG_BAD"] / stats["AVG_BAD"].mean()
64
+ stats["VAR"] = var
65
+
66
+ stats = stats.rename(columns={"_BIN_NUM": "BIN_NUM", "_BIN_RANGE": "BIN_RANGE"})
67
+
68
+ cols = ["VAR", "BIN_NUM", "BIN_RANGE", "MIN", "MAX", "N",
69
+ "AVG_BAD", "WOE", "IV", "N_BAD", "N_GOOD",
70
+ "BAD_PCT_PER_BIN", "GOOD_PCT_PER_BIN", "LIFT"]
71
+ stats = stats[cols]
72
+ all_tables.append(stats)
73
+
74
+ return pd.concat(all_tables, ignore_index=True)
75
+
76
+
77
+ def get_group_woe_table(woe_master, data, group, varlist=None):
78
+ """生成分组样本的WOE汇总、透视和详细表。"""
79
+ if varlist is None:
80
+ varlist = woe_master.varlist
81
+
82
+ summaries = []
83
+ pivots_woe = []
84
+ pivots_bad = []
85
+ detail_list = []
86
+
87
+ for var in varlist:
88
+ var_map = woe_master.woe_dict[var]
89
+ edges = get_bin_range_list(var_map, col="BIN_RANGE")
90
+ custom_edges = sorted(set(list(edges) + [-np.inf, np.inf]))
91
+ first_bin = var_map["BIN_RANGE"].dropna().iloc[0]
92
+ include_lowest = first_bin[0] == '['
93
+ right = first_bin[-1] == ']'
94
+ fill_val = woe_master.missing_ref_value
95
+
96
+ data_proc = data.copy()
97
+ data_proc[var] = data_proc[var].fillna(fill_val)
98
+
99
+ binned, _ = run_binning(
100
+ data=data_proc,
101
+ column=var,
102
+ nbins=custom_edges,
103
+ include_missing=True,
104
+ equal_freq=False,
105
+ bin_colnames=("_BIN_NUM", "_BIN_RANGE"),
106
+ ascending=True,
107
+ include_lowest=include_lowest,
108
+ right=right,
109
+ spec_values=[fill_val]
110
+ )
111
+
112
+ dep = woe_master.dep
113
+ # 按分箱与分组双重聚合
114
+ grp = binned.groupby([group, "_BIN_NUM", "_BIN_RANGE"], dropna=False)
115
+ stats = grp.agg(
116
+ MIN=(var, "min"),
117
+ MAX=(var, "max"),
118
+ N=(var, "count"),
119
+ AVG_BAD=(dep, "mean"),
120
+ N_BAD=(dep, "sum"),
121
+ N_GOOD=(dep, lambda x: (x == 0).sum())
122
+ ).reset_index()
123
+
124
+ # 计算各分箱内 WOE(全局分母)
125
+ total_bad = stats["N_BAD"].sum()
126
+ total_good = stats["N_GOOD"].sum()
127
+ stats["BAD_PCT_PER_BIN"] = stats["N_BAD"] / total_bad
128
+ stats["GOOD_PCT_PER_BIN"] = stats["N_GOOD"] / total_good
129
+ stats["WOE"] = calc_woe(stats, bad_pct="BAD_PCT_PER_BIN", good_pct="GOOD_PCT_PER_BIN")
130
+ stats["IV"] = calc_iv(stats, bad_pct="BAD_PCT_PER_BIN", good_pct="GOOD_PCT_PER_BIN")
131
+ stats["LIFT"] = stats["AVG_BAD"] / stats["AVG_BAD"].mean()
132
+ stats["VAR"] = var
133
+
134
+ # 生成透视表:WOE 和 AVG_BAD 在不同分组下的值
135
+ pvt_woe = stats.pivot_table(index=["_BIN_NUM", "_BIN_RANGE"], columns=group, values="WOE")
136
+ pvt_bad = stats.pivot_table(index=["_BIN_NUM", "_BIN_RANGE"], columns=group, values="AVG_BAD")
137
+
138
+ # 汇总各分组的总指标
139
+ sum_grp = stats.groupby(group).agg(
140
+ N=("N", "sum"),
141
+ IV=("IV", "sum"),
142
+ KS_PER_BIN=("LIFT", "max"), # 简化处理,可进一步细算
143
+ TOP_LIFT=("LIFT", "max"),
144
+ BTM_LIFT=("LIFT", "min")
145
+ ).reset_index()
146
+
147
+ # 计算单调性斜率(可选)
148
+ from Modeling_Tool.Core.Slope_Tool import calculate_slope_manual
149
+ slopes = stats.groupby(group).apply(lambda x: calculate_slope_manual(x, "AVG_BAD"))
150
+ sum_grp["SLOPE"] = sum_grp[group].map(slopes)
151
+ sum_grp["direction"] = sum_grp["SLOPE"].apply(lambda x: 1 if x > 0 else -1 if x < 0 else 0)
152
+ sum_grp["VAR"] = var
153
+
154
+ summaries.append(sum_grp)
155
+ pivots_woe.append(pvt_woe)
156
+ pivots_bad.append(pvt_bad)
157
+ detail_list.append(stats)
158
+
159
+ final_pivot = pd.concat(pivots_woe, keys=varlist, names=["VAR", "BIN_NUM", "BIN_RANGE"])
160
+ # 如需同时返回 AVG_BAD 透视表,可以合并或单独返回
161
+ return {
162
+ "summary": pd.concat(summaries, ignore_index=True),
163
+ "pivot": final_pivot,
164
+ "detail": pd.concat(detail_list, ignore_index=True)
165
+ }
166
+
167
+
168
+ class WOE_Master(object):
169
+ """WOE Master class for WOE fitting, transformation, adjustment and plotting.
170
+
171
+ This class provides a complete WOE encoding workflow including:
172
+ - Fitting WOE bins from data
173
+ - Loading existing WOE mapping tables
174
+ - Transforming new data with WOE
175
+ - Updating and adjusting WOE bins
176
+ - Plotting bivariate WOE comparison charts
177
+
178
+ Attributes:
179
+ train_data: pandas.DataFrame, training dataset
180
+ varlist: list, variable names for WOE transformation
181
+ dep: str, target variable name
182
+ graph_save_dir: str, directory for saving graphs
183
+ woe_suffix: str, suffix for WOE variable names
184
+ missing_ref_value: int/float, reference value for missing data
185
+ woe_dict: dict, WOE mapping dictionary
186
+ """
187
+
188
+ def __init__(self, train_data, varlist, dep=None, graph_save_dir="", woe_suffix="_woe", missing_ref_value=-999999, remove_exist_dir = False):
189
+ """Initialize WOE_Master instance.
190
+
191
+ Args:
192
+ train_data: pandas.DataFrame, training dataset with features and target
193
+ varlist: list, variables to perform WOE transformation
194
+ dep: str, target variable name
195
+ graph_save_dir: str, directory to save graphs
196
+ woe_suffix: str, suffix for WOE variable names
197
+ missing_ref_value: int/float, reference value for missing values
198
+ """
199
+ self.train_data = train_data
200
+ self.varlist = varlist
201
+ self.dep = dep
202
+ self.graph_save_dir = graph_save_dir
203
+ self.woe_suffix = woe_suffix
204
+ self.missing_ref_value = missing_ref_value
205
+ self.woe_dict = {}
206
+
207
+ if remove_exist_dir:
208
+ self.remove_folder(graph_save_dir)
209
+
210
+ @staticmethod
211
+ def remove_folder(file_path):
212
+ """删除指定文件夹。
213
+
214
+ 递归删除指定路径的文件夹及其所有内容,
215
+ 如果文件夹不存在则静默处理。
216
+
217
+ Parameters
218
+ ----------
219
+ file_path : str
220
+ 要删除的文件夹路径
221
+
222
+ Examples
223
+ --------
224
+ >>> VarExtractionInsights.remove_folder('/path/to/folder')
225
+ """
226
+ import shutil
227
+ try:
228
+ shutil.rmtree(file_path)
229
+ except Exception:
230
+ pass
231
+
232
+ def load_mapping_table(self, mapping_table_csv):
233
+ """Load WOE mapping table from CSV file or DataFrame.
234
+
235
+ Args:
236
+ mapping_table_csv: str or pandas.DataFrame, path to CSV or DataFrame object
237
+ Returns:
238
+ None, updates self.woe_dict and self.varlist attributes
239
+ Raises:
240
+ AttributeError: if input is neither string path nor DataFrame
241
+ """
242
+ if isinstance(mapping_table_csv, str):
243
+ woe_mapping_table = pd.read_csv(mapping_table_csv)
244
+ elif isinstance(mapping_table_csv, pd.DataFrame):
245
+ woe_mapping_table = mapping_table_csv
246
+ else:
247
+ raise AttributeError("Please give either CSV path or Pandas DataFrame as an input! ")
248
+
249
+ varlist = woe_mapping_table['VAR'].unique().tolist()
250
+
251
+ woe_dict = {}
252
+ for var in varlist:
253
+ single_var_woe = woe_mapping_table.query(f"VAR == '{var}'")
254
+ woe_dict[var] = single_var_woe
255
+
256
+ self.woe_dict = woe_dict
257
+ self.varlist = varlist
258
+
259
+ def fit(self, nbins=10, equal_freq=True, tree_binning_seed=None, chi2_config=None,
260
+ precision=5, min_bin_prop=0.05, include_missing=True, fillna=None, spec_values=[]):
261
+ """Fit WOE binning for variables in varlist.
262
+
263
+ Args:
264
+ nbins: int, number of bins (default 10)
265
+ equal_freq: bool, use equal frequency binning (default True)
266
+ tree_binning_seed: int, random seed for tree-based binning
267
+ chi2_config: dict, chi-square binning configuration
268
+ precision: int, numerical precision (default 5)
269
+ min_bin_prop: float, minimum bin proportion (default 0.05)
270
+ include_missing: bool, include missing value bin (default True)
271
+ fillna: int/float, value to fill missing data
272
+ spec_values: list, special values to handle
273
+ Returns:
274
+ None, updates self.woe_dict attribute
275
+ """
276
+ if fillna is None:
277
+ fillna = self.missing_ref_value
278
+
279
+ for var in self.varlist:
280
+ woe_res = woe_transform(train_df=self.train_data,
281
+ oot_df=None,
282
+ var=var,
283
+ dep=self.dep,
284
+ nbins=nbins,
285
+ chi2_config=chi2_config,
286
+ tree_binning_seed=tree_binning_seed,
287
+ precision=precision,
288
+ min_bin_prop=min_bin_prop,
289
+ include_missing=include_missing,
290
+ equal_freq=equal_freq,
291
+ ascending=True,
292
+ fillna=fillna,
293
+ spec_values=spec_values,
294
+ drop_bin_info=True,
295
+ ret_woe_table=True)
296
+ woe_table = woe_res[-1]
297
+ woe_table["VAR"] = var
298
+ woe_table = woe_table.rename(columns={f"_bin_num_{var}": "BIN_NUM", f"_bin_range_{var}": "BIN_RANGE"})
299
+ self.woe_dict[var] = woe_table
300
+
301
+ def get_mapping_table(self):
302
+ """Get WOE mapping table for all variables.
303
+
304
+ Returns:
305
+ pandas.DataFrame with WOE mapping information for all variables
306
+ """
307
+ return pd.concat([v for k, v in self.woe_dict.items()])
308
+
309
+ def save_mapping_table(self, save_dir):
310
+ """Save WOE mapping table as CSV file.
311
+
312
+ Args:
313
+ save_dir: str, path to save the CSV file
314
+ Returns:
315
+ None, saves file directly
316
+ """
317
+ mapping_table = self.get_mapping_table()
318
+ mapping_table.to_csv(save_dir, index=False)
319
+
320
+ def transform(self, data=None, varlist=None):
321
+ """Transform data using WOE encoding.
322
+
323
+ Args:
324
+ data: pandas.DataFrame, data to transform (default: train_data)
325
+ varlist: list, variables to transform (default: self.varlist)
326
+ Returns:
327
+ pandas.DataFrame with WOE transformed data
328
+ """
329
+ if data is None:
330
+ data = self.train_data
331
+ if varlist is None:
332
+ varlist = self.varlist
333
+
334
+ woe_mapping_table = self.get_mapping_table()
335
+ data_woe = mapping_woe(data, varlist, woe_mapping_table, suffix=self.woe_suffix, drop_bin_info=True)
336
+ return data_woe
337
+
338
+ def update_woe(self, varlist, nbins=10, equal_freq=True, tree_binning_seed=None, chi2_config=None,
339
+ precision=5, min_bin_prop=0.05, include_missing=True, fillna=None, spec_values=[]):
340
+ """Update WOE binning for specified variables.
341
+
342
+ Args:
343
+ varlist: list, variables to update WOE for
344
+ nbins: int, number of bins (default 10)
345
+ equal_freq: bool, use equal frequency binning (default True)
346
+ tree_binning_seed: int, random seed for tree-based binning
347
+ chi2_config: dict, chi-square binning configuration
348
+ precision: int, numerical precision (default 5)
349
+ min_bin_prop: float, minimum bin proportion (default 0.05)
350
+ include_missing: bool, include missing value bin (default True)
351
+ fillna: int/float, value to fill missing data
352
+ spec_values: list, special values to handle
353
+ Returns:
354
+ None, updates self.woe_dict attribute
355
+ """
356
+ if fillna is None:
357
+ fillna = self.missing_ref_value
358
+
359
+ new_woe_dict = {}
360
+ for var in varlist:
361
+ woe_res = woe_transform(train_df=self.train_data,
362
+ oot_df=None,
363
+ var=var,
364
+ dep=self.dep,
365
+ nbins=nbins,
366
+ chi2_config=chi2_config,
367
+ tree_binning_seed=tree_binning_seed,
368
+ precision=precision,
369
+ min_bin_prop=min_bin_prop,
370
+ include_missing=include_missing,
371
+ equal_freq=equal_freq,
372
+ ascending=True,
373
+ fillna=fillna,
374
+ spec_values=spec_values,
375
+ drop_bin_info=True,
376
+ ret_woe_table=True)
377
+ woe_table = woe_res[-1]
378
+ woe_table["VAR"] = var
379
+ woe_table = woe_table.rename(columns={f"_bin_num_{var}": "BIN_NUM", f"_bin_range_{var}": "BIN_RANGE"})
380
+ new_woe_dict[var] = woe_table
381
+
382
+ self.woe_dict.update(new_woe_dict)
383
+
384
+ def plot_bivar_graph(self, data, group, dirname, varlist=None):
385
+ """Plot bivariate WOE comparison graph.
386
+
387
+ Args:
388
+ data: pandas.DataFrame, data for plotting
389
+ group: str, grouping variable name for distinguishing curves
390
+ dirname: str, subdirectory name for saving (under graph_save_dir)
391
+ varlist: list, variables to plot (default: self.varlist)
392
+ Returns:
393
+ None, saves images directly
394
+ """
395
+ if varlist is None:
396
+ varlist = self.varlist
397
+
398
+ get_bivar_graph(data=data,
399
+ varlist=varlist,
400
+ sep=self.dep,
401
+ ref_woe_table=self.get_mapping_table(),
402
+ group=group,
403
+ save_dir=os.path.join(self.graph_save_dir, dirname))
404
+
405
+
406
+ # =============================================================================
407
+ # Standalone Function Wrappers
408
+ # =============================================================================
409
+
410
+ def load_mapping_table(mapping_table_csv):
411
+ """Load WOE mapping table from CSV or DataFrame.
412
+
413
+ Args:
414
+ mapping_table_csv: str or pandas.DataFrame, path to CSV or DataFrame
415
+ Returns:
416
+ tuple: (varlist, woe_dict)
417
+ Raises:
418
+ AttributeError: if input is neither string path nor DataFrame
419
+ """
420
+ if isinstance(mapping_table_csv, str):
421
+ woe_mapping_table = pd.read_csv(mapping_table_csv)
422
+ elif isinstance(mapping_table_csv, pd.DataFrame):
423
+ woe_mapping_table = mapping_table_csv
424
+ else:
425
+ raise AttributeError("Please give either CSV path or Pandas DataFrame as an input! ")
426
+
427
+ varlist = woe_mapping_table['VAR'].unique().tolist()
428
+ woe_dict = {}
429
+ for var in varlist:
430
+ single_var_woe = woe_mapping_table.query(f"VAR == '{var}'")
431
+ woe_dict[var] = single_var_woe
432
+ return varlist, woe_dict
433
+
434
+
435
+ def get_mapping_table(woe_dict):
436
+ """Get combined mapping table from WOE dictionary.
437
+
438
+ Args:
439
+ woe_dict: dict, WOE mapping dictionary
440
+ Returns:
441
+ pandas.DataFrame with WOE mapping information
442
+ """
443
+ return pd.concat([v for k, v in woe_dict.items()])
444
+
445
+
446
+ def save_mapping_table(woe_dict, save_dir):
447
+ """Save WOE dictionary as CSV file.
448
+
449
+ Args:
450
+ woe_dict: dict, WOE mapping dictionary
451
+ save_dir: str, path to save the CSV file
452
+ Returns:
453
+ None, saves file directly
454
+ """
455
+ mapping_table = get_mapping_table(woe_dict)
456
+ mapping_table.to_csv(save_dir, index=False)
457
+
458
+
459
+ def transform(data, varlist, woe_mapping_table, woe_suffix="_woe"):
460
+ """Transform data using WOE encoding.
461
+
462
+ Args:
463
+ data: pandas.DataFrame, data to transform
464
+ varlist: list, variables to transform
465
+ woe_mapping_table: pandas.DataFrame, WOE mapping table
466
+ woe_suffix: str, suffix for WOE variable names (default "_woe")
467
+ Returns:
468
+ pandas.DataFrame with WOE transformed data
469
+ """
470
+ return mapping_woe(data, varlist, woe_mapping_table, suffix=woe_suffix, drop_bin_info=True)
471
+
472
+
473
+ def plot_bivar_graph_func(data, varlist, dep, ref_woe_table, group, save_dir):
474
+ """Plot bivariate WOE comparison graph.
475
+
476
+ Args:
477
+ data: pandas.DataFrame, data for plotting
478
+ varlist: list, variables to plot
479
+ dep: str, target variable name
480
+ ref_woe_table: pandas.DataFrame, reference WOE mapping table
481
+ group: str, grouping variable name for distinguishing curves
482
+ save_dir: str, directory path to save images
483
+ Returns:
484
+ None, saves images directly
485
+ """
486
+ get_bivar_graph(data=data,
487
+ varlist=varlist,
488
+ sep=dep,
489
+ ref_woe_table=ref_woe_table,
490
+ group=group,
491
+ save_dir=save_dir)
@@ -0,0 +1,40 @@
1
+ # =============================================================================
2
+ # Modeling_Tool.WOE.WOE_Master
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2026 Kyle Sun <github.com/Kyle-J-Sun>. All rights reserved.
5
+ # SuperModelingFactory — Licensed under the Business Source License 1.1.
6
+ #
7
+ # This stub describes the public API of a closed-source module compiled to a
8
+ # native extension (.so / .pyd). The original source is not distributed.
9
+ # Production / commercial use requires a separate commercial license.
10
+ #
11
+ # FINGERPRINT: SMF-WOEMASTER-984661fa
12
+ # (Unique trace marker. Do not remove or alter — used for plagiarism
13
+ # detection across the public internet.)
14
+ # =============================================================================
15
+
16
+ import os
17
+ import pandas as pd
18
+ import numpy as np
19
+ from .WOE_Plot_Tool import get_bivar_graph
20
+ from .WOE_Tool import mapping_woe, woe_transform
21
+ from Modeling_Tool.Core.Binning_Tool import run_binning, get_bin_range_list
22
+ from Modeling_Tool.Core.utils import calc_woe, calc_iv
23
+ def get_overall_woe_table(woe_master, data, varlist = None): ...
24
+ def get_group_woe_table(woe_master, data, group, varlist = None): ...
25
+
26
+ class WOE_Master(object):
27
+ def __init__(self, train_data, varlist, dep = None, graph_save_dir = '', woe_suffix = '_woe', missing_ref_value = -999999, remove_exist_dir = False): ...
28
+ def remove_folder(file_path): ...
29
+ def load_mapping_table(self, mapping_table_csv): ...
30
+ def fit(self, nbins = 10, equal_freq = True, tree_binning_seed = None, chi2_config = None, precision = 5, min_bin_prop = 0.05, include_missing = True, fillna = None, spec_values = []): ...
31
+ def get_mapping_table(self): ...
32
+ def save_mapping_table(self, save_dir): ...
33
+ def transform(self, data = None, varlist = None): ...
34
+ def update_woe(self, varlist, nbins = 10, equal_freq = True, tree_binning_seed = None, chi2_config = None, precision = 5, min_bin_prop = 0.05, include_missing = True, fillna = None, spec_values = []): ...
35
+ def plot_bivar_graph(self, data, group, dirname, varlist = None): ...
36
+ def load_mapping_table(mapping_table_csv): ...
37
+ def get_mapping_table(woe_dict): ...
38
+ def save_mapping_table(woe_dict, save_dir): ...
39
+ def transform(data, varlist, woe_mapping_table, woe_suffix = '_woe'): ...
40
+ def plot_bivar_graph_func(data, varlist, dep, ref_woe_table, group, save_dir): ...