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.
- ExcelMaster/ExcelFormatTool.py +487 -0
- ExcelMaster/ExcelMaster.py +917 -0
- ExcelMaster/Template.py +525 -0
- ExcelMaster/Utility.py +233 -0
- ExcelMaster/__init__.py +3 -0
- Modeling_Tool/Core/Binning_Tool.py +1608 -0
- Modeling_Tool/Core/Binning_Tool.pyi +48 -0
- Modeling_Tool/Core/Check_DuckDB_Compatibility.py +835 -0
- Modeling_Tool/Core/Json_Data_Converter.py +621 -0
- Modeling_Tool/Core/Model_Registry_Tool.py +199 -0
- Modeling_Tool/Core/ODPS_Tool.py +284 -0
- Modeling_Tool/Core/Slope_Tool.py +356 -0
- Modeling_Tool/Core/Slope_Tool.pyi +31 -0
- Modeling_Tool/Core/XOR_Encryptor.py +207 -0
- Modeling_Tool/Core/XOR_Encryptor.pyi +26 -0
- Modeling_Tool/Core/__init__.py +99 -0
- Modeling_Tool/Core/kDataFrame.py +228 -0
- Modeling_Tool/Core/kDataFrame.pyi +43 -0
- Modeling_Tool/Core/sample_weight_utils.py +77 -0
- Modeling_Tool/Core/utils.py +2672 -0
- Modeling_Tool/Eval/Evaluation_Tool.py +1452 -0
- Modeling_Tool/Eval/Evaluation_Tool.pyi +47 -0
- Modeling_Tool/Eval/Model_Eval_Tool.py +2548 -0
- Modeling_Tool/Eval/Model_Eval_Tool.pyi +37 -0
- Modeling_Tool/Eval/__init__.py +54 -0
- Modeling_Tool/Eval/evaluate_model.py +2008 -0
- Modeling_Tool/Eval/evaluate_model.pyi +50 -0
- Modeling_Tool/Eval/weighted_eval_utils.py +326 -0
- Modeling_Tool/Explainability/Coalition_Structure.py +305 -0
- Modeling_Tool/Explainability/Model_Explainer.py +743 -0
- Modeling_Tool/Explainability/__init__.py +24 -0
- Modeling_Tool/Feature/Distribution_Tool.py +509 -0
- Modeling_Tool/Feature/Distribution_Tool.pyi +42 -0
- Modeling_Tool/Feature/Feature_Insights.py +762 -0
- Modeling_Tool/Feature/Feature_Insights.pyi +33 -0
- Modeling_Tool/Feature/PSI_Tool.py +1195 -0
- Modeling_Tool/Feature/PSI_Tool.pyi +29 -0
- Modeling_Tool/Feature/WOE_Engine_Feature_Patch.py +355 -0
- Modeling_Tool/Feature/__init__.py +40 -0
- Modeling_Tool/Model/Backward_Tool.py +778 -0
- Modeling_Tool/Model/Backward_Tool.pyi +45 -0
- Modeling_Tool/Model/GBM_Search_Tool.py +251 -0
- Modeling_Tool/Model/GBM_Tool.py +1610 -0
- Modeling_Tool/Model/GBM_Tool.pyi +90 -0
- Modeling_Tool/Model/LRM_Tool.py +1198 -0
- Modeling_Tool/Model/LRM_Tool.pyi +47 -0
- Modeling_Tool/Model/__init__.py +61 -0
- Modeling_Tool/Sample/Distribution_Adaptation.py +131 -0
- Modeling_Tool/Sample/Distribution_Adaptation.pyi +30 -0
- Modeling_Tool/Sample/Reject_Infer.py +413 -0
- Modeling_Tool/Sample/Reject_Infer.pyi +43 -0
- Modeling_Tool/Sample/Sample_Split.py +520 -0
- Modeling_Tool/Sample/Sample_Split.pyi +43 -0
- Modeling_Tool/Sample/__init__.py +31 -0
- Modeling_Tool/UAT/UAT_Consistency_Checker.py +1180 -0
- Modeling_Tool/UAT/__init__.py +19 -0
- Modeling_Tool/WOE/WOE_Adapter.py +204 -0
- Modeling_Tool/WOE/WOE_Adapter.pyi +21 -0
- Modeling_Tool/WOE/WOE_Master.py +491 -0
- Modeling_Tool/WOE/WOE_Master.pyi +40 -0
- Modeling_Tool/WOE/WOE_Monotone_Binner.py +3324 -0
- Modeling_Tool/WOE/WOE_Monotone_Binner.pyi +71 -0
- Modeling_Tool/WOE/WOE_Plot_Tool.py +919 -0
- Modeling_Tool/WOE/WOE_Plot_Tool.pyi +46 -0
- Modeling_Tool/WOE/WOE_Report_Builder.py +214 -0
- Modeling_Tool/WOE/WOE_Report_Builder.pyi +24 -0
- Modeling_Tool/WOE/WOE_Tool.py +1094 -0
- Modeling_Tool/WOE/WOE_Tool.pyi +41 -0
- Modeling_Tool/WOE/__init__.py +86 -0
- Modeling_Tool/WOE/plot_woe_tool.py +290 -0
- Modeling_Tool/WOE/plot_woe_tool.pyi +25 -0
- Modeling_Tool/__init__.py +176 -0
- Report/Report_Tool.py +380 -0
- Report/__init__.py +3 -0
- supermodelingfactory-0.2.0.dist-info/METADATA +268 -0
- supermodelingfactory-0.2.0.dist-info/RECORD +79 -0
- supermodelingfactory-0.2.0.dist-info/WHEEL +5 -0
- supermodelingfactory-0.2.0.dist-info/licenses/LICENSE +102 -0
- supermodelingfactory-0.2.0.dist-info/top_level.txt +3 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from .Binning_Tool import (
|
|
2
|
+
Binning,
|
|
3
|
+
chi2_binning,
|
|
4
|
+
run_binning,
|
|
5
|
+
super_binning,
|
|
6
|
+
get_max_nbins,
|
|
7
|
+
get_decision_tree_binning_edges,
|
|
8
|
+
NumVarBinning,
|
|
9
|
+
cre_pvt,
|
|
10
|
+
merge_bins,
|
|
11
|
+
observed_laplace,
|
|
12
|
+
cat_2_list,
|
|
13
|
+
get_bin_range,
|
|
14
|
+
get_bin_range_list,
|
|
15
|
+
chi2_auto_binning,
|
|
16
|
+
quick_binning,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
def __getattr__(name):
|
|
20
|
+
if name == "ODPSRunner":
|
|
21
|
+
from .ODPS_Tool import ODPSRunner as _ODPSRunner
|
|
22
|
+
return _ODPSRunner
|
|
23
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
24
|
+
|
|
25
|
+
from .Slope_Tool import (
|
|
26
|
+
calculate_slope_sklearn,
|
|
27
|
+
calculate_slope_scipy,
|
|
28
|
+
calculate_slope_numpy,
|
|
29
|
+
calculate_slope_manual,
|
|
30
|
+
SlopeCalculator,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from .sample_weight_utils import (
|
|
34
|
+
resolve_sample_weight,
|
|
35
|
+
validate_sample_weight,
|
|
36
|
+
weighted_sum,
|
|
37
|
+
weighted_mean,
|
|
38
|
+
weighted_rate,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
from .utils import (
|
|
42
|
+
cut2pieces,
|
|
43
|
+
proc_freq,
|
|
44
|
+
read_attr_list,
|
|
45
|
+
write_attr_list,
|
|
46
|
+
odds_score,
|
|
47
|
+
parse_odps_schema,
|
|
48
|
+
npnan2none,
|
|
49
|
+
drop_tmp_cols,
|
|
50
|
+
mkdir_if_not_exist,
|
|
51
|
+
parse_sql_file,
|
|
52
|
+
calc_woe,
|
|
53
|
+
calc_iv,
|
|
54
|
+
scoring,
|
|
55
|
+
get_missing_indicator,
|
|
56
|
+
upload_score,
|
|
57
|
+
DataFrameProcessor,
|
|
58
|
+
FilePathManager,
|
|
59
|
+
DateTimeUtils,
|
|
60
|
+
WOEIVCalculator,
|
|
61
|
+
get_feature_names,
|
|
62
|
+
get_feature_names_lgb,
|
|
63
|
+
get_feature_names_xgb,
|
|
64
|
+
get_feature_names_batch,
|
|
65
|
+
pull_attributes_in_batch,
|
|
66
|
+
)
|
|
67
|
+
from .Model_Registry_Tool import (
|
|
68
|
+
make_model_artifact,
|
|
69
|
+
save_model,
|
|
70
|
+
load_model,
|
|
71
|
+
load_model_metadata,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
from .XOR_Encryptor import TextEncryptor
|
|
75
|
+
|
|
76
|
+
from .kDataFrame import kSeries, kDataFrame
|
|
77
|
+
|
|
78
|
+
__all__ = [
|
|
79
|
+
'Binning', 'chi2_binning', 'run_binning', 'super_binning',
|
|
80
|
+
'get_max_nbins', 'get_decision_tree_binning_edges', 'NumVarBinning',
|
|
81
|
+
'cre_pvt', 'merge_bins', 'observed_laplace', 'cat_2_list',
|
|
82
|
+
'get_bin_range', 'get_bin_range_list', 'chi2_auto_binning', 'quick_binning',
|
|
83
|
+
'ODPSRunner',
|
|
84
|
+
'calculate_slope_sklearn', 'calculate_slope_scipy',
|
|
85
|
+
'calculate_slope_numpy', 'calculate_slope_manual',
|
|
86
|
+
'SlopeCalculator',
|
|
87
|
+
'resolve_sample_weight', 'validate_sample_weight',
|
|
88
|
+
'weighted_sum', 'weighted_mean', 'weighted_rate',
|
|
89
|
+
'cut2pieces', 'proc_freq', 'read_attr_list', 'write_attr_list',
|
|
90
|
+
'odds_score', 'parse_odps_schema', 'npnan2none', 'drop_tmp_cols',
|
|
91
|
+
'mkdir_if_not_exist', 'parse_sql_file', 'calc_woe', 'calc_iv',
|
|
92
|
+
'save_model', 'load_model', 'load_model_metadata', 'make_model_artifact',
|
|
93
|
+
'scoring', 'get_missing_indicator', 'upload_score',
|
|
94
|
+
'get_feature_names', 'get_feature_names_lgb', 'get_feature_names_xgb',
|
|
95
|
+
'get_feature_names_batch', 'pull_attributes_in_batch',
|
|
96
|
+
'DataFrameProcessor', 'FilePathManager', 'DateTimeUtils', 'WOEIVCalculator',
|
|
97
|
+
'TextEncryptor',
|
|
98
|
+
'kSeries', 'kDataFrame',
|
|
99
|
+
]
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from pandas import DataFrame
|
|
5
|
+
from pandas import Series
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
# Available only in newer pandas versions. Older Airflow images should skip it.
|
|
9
|
+
try:
|
|
10
|
+
pd.set_option('future.no_silent_downcasting', True)
|
|
11
|
+
except (KeyError, ValueError):
|
|
12
|
+
pass
|
|
13
|
+
pd.options.mode.chained_assignment = None # default='warn'
|
|
14
|
+
|
|
15
|
+
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
16
|
+
|
|
17
|
+
class kSeries(Series):
|
|
18
|
+
@property
|
|
19
|
+
def _constructor(self):
|
|
20
|
+
return kSeries
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def _constructor_expanddim(self):
|
|
24
|
+
return kDataFrame
|
|
25
|
+
|
|
26
|
+
def __init__(self, data, *args, **kwargs):
|
|
27
|
+
super().__init__(data, *args, **kwargs)
|
|
28
|
+
|
|
29
|
+
def to_pdSeries(self, inplace: bool = False):
|
|
30
|
+
"""
|
|
31
|
+
Convert kSeries back to pandas Series.
|
|
32
|
+
"""
|
|
33
|
+
if inplace:
|
|
34
|
+
data = self
|
|
35
|
+
else:
|
|
36
|
+
data = self.copy()
|
|
37
|
+
|
|
38
|
+
df = Series(data)
|
|
39
|
+
return df
|
|
40
|
+
|
|
41
|
+
def odds_score(self):
|
|
42
|
+
"""
|
|
43
|
+
Calculate the odd score based on the given probability score.
|
|
44
|
+
|
|
45
|
+
Odds Score = (count of sth happening) / (count of sth not happening)
|
|
46
|
+
Odds Score = pb_score / (1-pb_score) [This ranges from 0 to infinity.]
|
|
47
|
+
Log Odds Score = np.log(pb_score / (1-pb_score)) [This ranges from -infinity to +infinity]
|
|
48
|
+
This is helpful for solving binary classification problem.
|
|
49
|
+
Odds Ratio: The ratio of odds.
|
|
50
|
+
"""
|
|
51
|
+
pb_score = self
|
|
52
|
+
a = (20 / np.log(2))
|
|
53
|
+
b = (np.log(15) + np.log(pb_score/(1 - pb_score)))
|
|
54
|
+
return (500 - a * b)
|
|
55
|
+
|
|
56
|
+
def scale_score(self):
|
|
57
|
+
"""
|
|
58
|
+
Scale the model scores (for internt segment of MCI model)
|
|
59
|
+
"""
|
|
60
|
+
data = self.copy()
|
|
61
|
+
def app_func(x):
|
|
62
|
+
scores = x * 1.112
|
|
63
|
+
if (scores > 0.9999999):
|
|
64
|
+
return 0.9999999
|
|
65
|
+
return scores
|
|
66
|
+
return data.apply(app_func)
|
|
67
|
+
|
|
68
|
+
def proc_freq(self) -> pd.DataFrame:
|
|
69
|
+
"""
|
|
70
|
+
Implement the Python version "proc freq" query in SAS.
|
|
71
|
+
"""
|
|
72
|
+
data = self.copy()
|
|
73
|
+
f = data.value_counts(dropna = False)
|
|
74
|
+
p = data.value_counts(dropna = False, normalize = True)
|
|
75
|
+
df = pd.concat([f,p], axis = 1, keys = ['frequency', 'percent'])
|
|
76
|
+
df['cumFrequency'] = df['frequency'].cumsum()
|
|
77
|
+
df['cumPercent'] = df['percent'].cumsum()
|
|
78
|
+
return df
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class kDataFrame(DataFrame):
|
|
83
|
+
"""
|
|
84
|
+
The extension class of Pandas DataFrame including more useful methods to manipulate dataset.
|
|
85
|
+
|
|
86
|
+
Parameters:
|
|
87
|
+
-----------
|
|
88
|
+
data [DataFrame]: Any pandas dataframe dataset.
|
|
89
|
+
|
|
90
|
+
Return:
|
|
91
|
+
-------
|
|
92
|
+
data [kDataFrame]: the extension object of dataframe.
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
_metadata = ['added_property']
|
|
96
|
+
added_property = 1 # This will be passed to copies
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def _constructor(self):
|
|
100
|
+
return kDataFrame
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def _constructor_sliced(self):
|
|
104
|
+
return kSeries
|
|
105
|
+
|
|
106
|
+
def __init__(self, data, *args, **kwargs):
|
|
107
|
+
super().__init__(data, *args, **kwargs)
|
|
108
|
+
|
|
109
|
+
def move_column(self, colname: str, idx: int, inplace: bool = False):
|
|
110
|
+
"""
|
|
111
|
+
To move a column into specific place by index.
|
|
112
|
+
"""
|
|
113
|
+
if inplace:
|
|
114
|
+
data = self
|
|
115
|
+
else:
|
|
116
|
+
data = self.copy()
|
|
117
|
+
colarray = data.columns.tolist()
|
|
118
|
+
colarray.remove(colname)
|
|
119
|
+
colarray.insert(idx, colname)
|
|
120
|
+
data = data[colarray]
|
|
121
|
+
return data
|
|
122
|
+
|
|
123
|
+
def convert_to_vintage(self, vintage_colname: str = 'VINTAGE', by: str = 'TRAN_TMS', inplace: bool = False):
|
|
124
|
+
"""
|
|
125
|
+
To obtain a vintage column by a time/data column.
|
|
126
|
+
"""
|
|
127
|
+
if inplace:
|
|
128
|
+
data = self
|
|
129
|
+
else:
|
|
130
|
+
data = self.copy()
|
|
131
|
+
import re
|
|
132
|
+
data[vintage_colname] = data[by].apply(lambda x: re.search("\d{4}-\d{2}", x).group().replace('-', ''))
|
|
133
|
+
if inplace:
|
|
134
|
+
self = data
|
|
135
|
+
return data
|
|
136
|
+
|
|
137
|
+
def col_filter_regex(self, regex: str = ".*?of_co_at_12m", case_sensitive = True, inplace: bool = False):
|
|
138
|
+
"""
|
|
139
|
+
To filter the DataFrame columns by regular expression.
|
|
140
|
+
"""
|
|
141
|
+
if inplace:
|
|
142
|
+
data = self
|
|
143
|
+
else:
|
|
144
|
+
data = self.copy()
|
|
145
|
+
|
|
146
|
+
fltr = data.columns[data.columns.str.contains(regex, regex = True, case = case_sensitive)]
|
|
147
|
+
return data[fltr]
|
|
148
|
+
|
|
149
|
+
def row_filter_regex(self, col = None, regex: str = None, case_sensitive = True,
|
|
150
|
+
as_index = False, inplace: bool = False):
|
|
151
|
+
"""
|
|
152
|
+
To filter the string format row using regex.
|
|
153
|
+
"""
|
|
154
|
+
if inplace:
|
|
155
|
+
data = self
|
|
156
|
+
else:
|
|
157
|
+
data = self.copy()
|
|
158
|
+
|
|
159
|
+
fltr = data[col].astype('str').str.contains(pat = regex, regex = True, case = case_sensitive)
|
|
160
|
+
if as_index:
|
|
161
|
+
return data[fltr].set_index(col)
|
|
162
|
+
return data[fltr]
|
|
163
|
+
|
|
164
|
+
def scale_score(self, pb_score: str):
|
|
165
|
+
"""
|
|
166
|
+
Scale the model scores (for internt segment of MCI model)
|
|
167
|
+
"""
|
|
168
|
+
data = self.copy()
|
|
169
|
+
def app_func(x):
|
|
170
|
+
scores = x * 1.112
|
|
171
|
+
if (scores > 0.9999999):
|
|
172
|
+
return 0.9999999
|
|
173
|
+
return scores
|
|
174
|
+
return data[pb_score].apply(app_func)
|
|
175
|
+
|
|
176
|
+
def proc_freq(self, var: str):
|
|
177
|
+
"""
|
|
178
|
+
Implement the Python version "proc freq" query in SAS.
|
|
179
|
+
"""
|
|
180
|
+
data = self.copy()
|
|
181
|
+
f = data[var].value_counts(dropna = False)
|
|
182
|
+
p = data[var].value_counts(dropna = False, normalize = True)
|
|
183
|
+
df = pd.concat([f,p], axis = 1, keys = ['frequency', 'percent'])
|
|
184
|
+
df['cumFrequency'] = df['frequency'].cumsum()
|
|
185
|
+
df['cumPercent'] = df['percent'].cumsum()
|
|
186
|
+
return df
|
|
187
|
+
|
|
188
|
+
def unify_table_col_names(self, how: str = "lowercase", inplace: bool = False):
|
|
189
|
+
"""
|
|
190
|
+
Unify the format of column names.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
if inplace:
|
|
194
|
+
data = self
|
|
195
|
+
else:
|
|
196
|
+
data = self.copy()
|
|
197
|
+
|
|
198
|
+
cols = data.columns
|
|
199
|
+
if how.lower() == "lower" or how.lower() == "lowercase":
|
|
200
|
+
res = [name.lower() for name in cols]
|
|
201
|
+
if how.lower() == "upper" or how.lower() == "uppercase":
|
|
202
|
+
res = [name.upper() for name in cols]
|
|
203
|
+
if how.lower() == "cap" or how.lower() == "capitalize":
|
|
204
|
+
res = [name.capitalize() for name in cols]
|
|
205
|
+
data.columns = res
|
|
206
|
+
return data
|
|
207
|
+
|
|
208
|
+
def convert_strlist_to_list(self, col: str):
|
|
209
|
+
"""
|
|
210
|
+
cast string-type lists in a specified Series into real lists.
|
|
211
|
+
"""
|
|
212
|
+
import re
|
|
213
|
+
|
|
214
|
+
data = self.copy()
|
|
215
|
+
str_col = kSeries([re.findall("\w+", str(x)) for x in data[col]])
|
|
216
|
+
return str_col
|
|
217
|
+
|
|
218
|
+
def to_pdDataFrame(self, inplace: bool = False):
|
|
219
|
+
"""
|
|
220
|
+
Convert df_extension back to DataFrame.
|
|
221
|
+
"""
|
|
222
|
+
if inplace:
|
|
223
|
+
data = self
|
|
224
|
+
else:
|
|
225
|
+
data = self.copy()
|
|
226
|
+
|
|
227
|
+
df = DataFrame(data)
|
|
228
|
+
return df
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Modeling_Tool.Core.kDataFrame
|
|
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-KDATAFRAME-76c89511
|
|
12
|
+
# (Unique trace marker. Do not remove or alter — used for plagiarism
|
|
13
|
+
# detection across the public internet.)
|
|
14
|
+
# =============================================================================
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import pandas as pd
|
|
18
|
+
from pandas import DataFrame
|
|
19
|
+
from pandas import Series
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
class kSeries(Series):
|
|
23
|
+
def _constructor(self): ...
|
|
24
|
+
def _constructor_expanddim(self): ...
|
|
25
|
+
def __init__(self, data, *args, **kwargs): ...
|
|
26
|
+
def to_pdSeries(self, inplace: bool = False): ...
|
|
27
|
+
def odds_score(self): ...
|
|
28
|
+
def scale_score(self): ...
|
|
29
|
+
def proc_freq(self) -> pd.DataFrame: ...
|
|
30
|
+
|
|
31
|
+
class kDataFrame(DataFrame):
|
|
32
|
+
def _constructor(self): ...
|
|
33
|
+
def _constructor_sliced(self): ...
|
|
34
|
+
def __init__(self, data, *args, **kwargs): ...
|
|
35
|
+
def move_column(self, colname: str, idx: int, inplace: bool = False): ...
|
|
36
|
+
def convert_to_vintage(self, vintage_colname: str = 'VINTAGE', by: str = 'TRAN_TMS', inplace: bool = False): ...
|
|
37
|
+
def col_filter_regex(self, regex: str = '.*?of_co_at_12m', case_sensitive = True, inplace: bool = False): ...
|
|
38
|
+
def row_filter_regex(self, col = None, regex: str = None, case_sensitive = True, as_index = False, inplace: bool = False): ...
|
|
39
|
+
def scale_score(self, pb_score: str): ...
|
|
40
|
+
def proc_freq(self, var: str): ...
|
|
41
|
+
def unify_table_col_names(self, how: str = 'lowercase', inplace: bool = False): ...
|
|
42
|
+
def convert_strlist_to_list(self, col: str): ...
|
|
43
|
+
def to_pdDataFrame(self, inplace: bool = False): ...
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
"""Sample-weight resolution and weighted aggregation helpers."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def resolve_sample_weight(
|
|
9
|
+
data=None,
|
|
10
|
+
weight_col=None,
|
|
11
|
+
sample_weight=None,
|
|
12
|
+
expected_len=None,
|
|
13
|
+
wgt=None,
|
|
14
|
+
wgt_col=None,
|
|
15
|
+
):
|
|
16
|
+
"""Resolve sample weights from a DataFrame column or array.
|
|
17
|
+
|
|
18
|
+
Accepts ``weight_col`` / ``wgt_col`` and ``sample_weight`` / ``wgt`` aliases.
|
|
19
|
+
Returns ``None`` when no weight source is provided.
|
|
20
|
+
"""
|
|
21
|
+
if weight_col is None:
|
|
22
|
+
weight_col = wgt_col
|
|
23
|
+
if sample_weight is None:
|
|
24
|
+
sample_weight = wgt
|
|
25
|
+
|
|
26
|
+
if sample_weight is not None and weight_col is not None:
|
|
27
|
+
raise ValueError("Provide either weight_col or sample_weight, not both.")
|
|
28
|
+
|
|
29
|
+
if weight_col is not None:
|
|
30
|
+
if data is None:
|
|
31
|
+
raise ValueError("data is required when weight_col is provided.")
|
|
32
|
+
if weight_col not in data.columns:
|
|
33
|
+
raise KeyError("weight column '{0}' not found in data".format(weight_col))
|
|
34
|
+
sample_weight = data[weight_col].values
|
|
35
|
+
|
|
36
|
+
if sample_weight is None:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
return validate_sample_weight(sample_weight, expected_len=expected_len)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def validate_sample_weight(weights, expected_len=None):
|
|
43
|
+
"""Validate and return a 1-D float numpy weight vector."""
|
|
44
|
+
w = np.asarray(weights, dtype=float)
|
|
45
|
+
if w.ndim != 1:
|
|
46
|
+
raise ValueError("sample_weight must be 1-dimensional.")
|
|
47
|
+
if expected_len is not None and len(w) != expected_len:
|
|
48
|
+
raise ValueError(
|
|
49
|
+
"sample_weight length {0} != expected {1}".format(len(w), expected_len)
|
|
50
|
+
)
|
|
51
|
+
if not np.all(np.isfinite(w)):
|
|
52
|
+
raise ValueError("sample_weight must be finite (no NaN/inf).")
|
|
53
|
+
if np.any(w < 0):
|
|
54
|
+
raise ValueError("sample_weight must be non-negative.")
|
|
55
|
+
return w
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def weighted_sum(values, weights):
|
|
59
|
+
"""Weighted sum of values."""
|
|
60
|
+
v = np.asarray(values, dtype=float)
|
|
61
|
+
w = np.asarray(weights, dtype=float)
|
|
62
|
+
return float(np.sum(v * w))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def weighted_mean(values, weights):
|
|
66
|
+
"""Weighted mean; returns NaN when total weight is zero."""
|
|
67
|
+
w = np.asarray(weights, dtype=float)
|
|
68
|
+
total = float(np.sum(w))
|
|
69
|
+
if total == 0:
|
|
70
|
+
return np.nan
|
|
71
|
+
return weighted_sum(values, weights) / total
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def weighted_rate(mask, weights):
|
|
75
|
+
"""Weighted rate of True / 1 values in mask."""
|
|
76
|
+
m = np.asarray(mask, dtype=float)
|
|
77
|
+
return weighted_mean(m, weights)
|