classifier-toolkit 0.1.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.
- classifier_toolkit/eda/__init__.py +19 -0
- classifier_toolkit/eda/bivariate_analysis.py +413 -0
- classifier_toolkit/eda/eda_toolkit.py +549 -0
- classifier_toolkit/eda/feature_engineering.py +1310 -0
- classifier_toolkit/eda/first_glance.py +253 -0
- classifier_toolkit/eda/univariate_analysis.py +778 -0
- classifier_toolkit/eda/visualizations.py +1248 -0
- classifier_toolkit/eda/warnings/__init__.py +4 -0
- classifier_toolkit/eda/warnings/automated_warnings.py +20 -0
- classifier_toolkit/eda/warnings/default_warnings.py +286 -0
- classifier_toolkit/feature_selection/__init__.py +33 -0
- classifier_toolkit/feature_selection/base.py +182 -0
- classifier_toolkit/feature_selection/embedded_methods/__init__.py +7 -0
- classifier_toolkit/feature_selection/embedded_methods/elastic_net.py +178 -0
- classifier_toolkit/feature_selection/meta_selector.py +329 -0
- classifier_toolkit/feature_selection/utils/__init__.py +17 -0
- classifier_toolkit/feature_selection/utils/plottings.py +65 -0
- classifier_toolkit/feature_selection/utils/scoring.py +86 -0
- classifier_toolkit/feature_selection/wrapper_methods/__init__.py +11 -0
- classifier_toolkit/feature_selection/wrapper_methods/rfe.py +345 -0
- classifier_toolkit/feature_selection/wrapper_methods/sequential_selection.py +566 -0
- classifier_toolkit/model_fitting/__init__.py +0 -0
- classifier_toolkit/model_fitting/model_search.py +3 -0
- classifier_toolkit-0.1.0.dist-info/METADATA +99 -0
- classifier_toolkit-0.1.0.dist-info/RECORD +26 -0
- classifier_toolkit-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
from datetime import date, datetime
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from examples.constants import PATH_DATA_PROCESSED
|
|
8
|
+
|
|
9
|
+
from .bivariate_analysis import BivariateAnalysis
|
|
10
|
+
from .feature_engineering import FeatureEngineering
|
|
11
|
+
from .first_glance import FirstGlance
|
|
12
|
+
from .univariate_analysis import UnivariateAnalysis
|
|
13
|
+
from .visualizations import Visualizations
|
|
14
|
+
from .warnings import EDAWarning, WarningSystem, get_default_warnings
|
|
15
|
+
|
|
16
|
+
# Define the type for the transformations list
|
|
17
|
+
TransformationType = List[Dict[str, Union[str, Dict[str, Any]]]]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EDAToolkit:
|
|
21
|
+
@staticmethod
|
|
22
|
+
def save_intermediary(path: Path, interm: pd.DataFrame, fname: str):
|
|
23
|
+
"""
|
|
24
|
+
Save an intermediary DataFrame to a CSV file.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
path : Path
|
|
29
|
+
The directory path where the CSV file will be saved.
|
|
30
|
+
interm : pd.DataFrame
|
|
31
|
+
The DataFrame to save.
|
|
32
|
+
fname : str
|
|
33
|
+
The file name for the CSV file (without extension).
|
|
34
|
+
"""
|
|
35
|
+
if not path:
|
|
36
|
+
raise ValueError(
|
|
37
|
+
"Please make sure to specify the path in the constants file."
|
|
38
|
+
)
|
|
39
|
+
else:
|
|
40
|
+
path_to_save = f"{path}/df_{fname}.csv"
|
|
41
|
+
interm.to_csv(path_to_save, index=False)
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
dataframe: pd.DataFrame,
|
|
46
|
+
can_be_negative: List[str],
|
|
47
|
+
target_column: Optional[str] = None,
|
|
48
|
+
exclusion: Optional[List[str]] = None,
|
|
49
|
+
numerical_columns: Optional[List[str]] = None,
|
|
50
|
+
categorical_columns: Optional[List[str]] = None,
|
|
51
|
+
id_column: Optional[str] = None,
|
|
52
|
+
to_be_enc: Optional[List[str]] = None,
|
|
53
|
+
warning_system: Optional[WarningSystem] = None,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Initialize the EDAToolkit class with data and configuration settings.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
dataframe : pd.DataFrame
|
|
61
|
+
The dataset to be analyzed.
|
|
62
|
+
can_be_negative : List[str]
|
|
63
|
+
List of columns where negative values are permissible.
|
|
64
|
+
target_column : Optional[str], optional
|
|
65
|
+
The target column for analysis, by default None.
|
|
66
|
+
exclusion : Optional[List[str]], optional
|
|
67
|
+
List of columns to exclude from analysis, by default None.
|
|
68
|
+
numerical_columns : Optional[List[str]], optional
|
|
69
|
+
List of numerical columns in the data, by default None.
|
|
70
|
+
categorical_columns : Optional[List[str]], optional
|
|
71
|
+
List of categorical columns in the data, by default None.
|
|
72
|
+
id_column : Optional[str], optional
|
|
73
|
+
Column used as an identifier, by default None.
|
|
74
|
+
to_be_enc : Optional[List[str]], optional
|
|
75
|
+
List of columns to be encoded, by default None.
|
|
76
|
+
warning_system : Optional[WarningSystem], optional
|
|
77
|
+
The warning system to use, by default None.
|
|
78
|
+
"""
|
|
79
|
+
self.dataframe = dataframe
|
|
80
|
+
self.target_column = target_column or ""
|
|
81
|
+
self.exclusion = exclusion or []
|
|
82
|
+
self.can_be_negative = can_be_negative
|
|
83
|
+
self.numerical_columns = numerical_columns or []
|
|
84
|
+
self.categorical_columns = categorical_columns or []
|
|
85
|
+
self.id_column = id_column or ""
|
|
86
|
+
self.to_be_enc = to_be_enc or []
|
|
87
|
+
|
|
88
|
+
# Initialize an empty list for transformations
|
|
89
|
+
self.transformations: TransformationType = []
|
|
90
|
+
|
|
91
|
+
# Initialize the warning system
|
|
92
|
+
default_warning_system = get_default_warnings(
|
|
93
|
+
df=self.dataframe,
|
|
94
|
+
target_column=self.target_column,
|
|
95
|
+
numerical_columns=self.numerical_columns,
|
|
96
|
+
can_be_negative=self.can_be_negative,
|
|
97
|
+
cardinality_exclusion=self.exclusion,
|
|
98
|
+
id_column=self.id_column,
|
|
99
|
+
)
|
|
100
|
+
self.warning_system = warning_system or WarningSystem(default_warning_system)
|
|
101
|
+
|
|
102
|
+
self.first_glance = FirstGlance(
|
|
103
|
+
self.dataframe,
|
|
104
|
+
self.numerical_columns,
|
|
105
|
+
self.categorical_columns,
|
|
106
|
+
exclusion,
|
|
107
|
+
id_column,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
self.visualizations = Visualizations(
|
|
111
|
+
self.dataframe,
|
|
112
|
+
self.target_column,
|
|
113
|
+
self.numerical_columns,
|
|
114
|
+
self.categorical_columns,
|
|
115
|
+
)
|
|
116
|
+
self.univariate_analysis = UnivariateAnalysis(
|
|
117
|
+
self.dataframe, self.target_column, self.numerical_columns
|
|
118
|
+
)
|
|
119
|
+
self.bivariate_analysis = BivariateAnalysis(
|
|
120
|
+
self.dataframe, self.numerical_columns
|
|
121
|
+
)
|
|
122
|
+
self.feature_engineering = FeatureEngineering(
|
|
123
|
+
self.dataframe,
|
|
124
|
+
self.target_column,
|
|
125
|
+
self.numerical_columns,
|
|
126
|
+
self.categorical_columns,
|
|
127
|
+
self.to_be_enc,
|
|
128
|
+
self.transformations,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def get_transformations(
|
|
132
|
+
self, unwanted_features: Optional[List] = None
|
|
133
|
+
) -> TransformationType:
|
|
134
|
+
"""
|
|
135
|
+
Get the list of transformations applied to the data.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
unwanted_features : Optional[List], optional
|
|
140
|
+
List of features to exclude from the transformations, by default None.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
TransformationType
|
|
145
|
+
A list of transformations.
|
|
146
|
+
"""
|
|
147
|
+
if unwanted_features:
|
|
148
|
+
for unwanted_feature in unwanted_features:
|
|
149
|
+
self.transformations = [
|
|
150
|
+
transform
|
|
151
|
+
for transform in self.transformations
|
|
152
|
+
if transform["feature"] != unwanted_feature
|
|
153
|
+
]
|
|
154
|
+
return self.transformations
|
|
155
|
+
|
|
156
|
+
def register_custom_warning(self, name: str, warning_obj: EDAWarning):
|
|
157
|
+
"""
|
|
158
|
+
Register a custom warning function.
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
name : str
|
|
163
|
+
The name of the custom warning.
|
|
164
|
+
func : WarningFunction
|
|
165
|
+
The warning function to register.
|
|
166
|
+
"""
|
|
167
|
+
self.warning_system.register_warning(name, warning_obj)
|
|
168
|
+
|
|
169
|
+
def print_warnings(self):
|
|
170
|
+
"""
|
|
171
|
+
Print all warnings for the dataset.
|
|
172
|
+
"""
|
|
173
|
+
warnings = self.warning_system.run_warnings()
|
|
174
|
+
|
|
175
|
+
for warning_name, warning_list in warnings.items():
|
|
176
|
+
if warning_list:
|
|
177
|
+
print(f"\n{warning_name.replace('_', ' ').title()} Warnings:")
|
|
178
|
+
print("-" * 50)
|
|
179
|
+
|
|
180
|
+
# Group warnings by type
|
|
181
|
+
grouped_warnings = {}
|
|
182
|
+
for warning in warning_list:
|
|
183
|
+
warning_type = warning["warning_type"]
|
|
184
|
+
if warning_type not in grouped_warnings:
|
|
185
|
+
grouped_warnings[warning_type] = []
|
|
186
|
+
grouped_warnings[warning_type].append(warning["message"])
|
|
187
|
+
|
|
188
|
+
for warning_type, messages in grouped_warnings.items():
|
|
189
|
+
print(f"{warning_type}:")
|
|
190
|
+
if len(messages) == 1 and ":" in messages[0]:
|
|
191
|
+
# For warnings with a single message containing a colon (like missing values)
|
|
192
|
+
header, values = messages[0].split(":", 1)
|
|
193
|
+
print(header.strip() + ":")
|
|
194
|
+
for item in values.strip().split(","):
|
|
195
|
+
print(f" {item.strip()}")
|
|
196
|
+
else:
|
|
197
|
+
# For other types of warnings
|
|
198
|
+
for message in messages:
|
|
199
|
+
print(f" {message}")
|
|
200
|
+
print("-" * 50)
|
|
201
|
+
|
|
202
|
+
def perform_checks(self):
|
|
203
|
+
"""
|
|
204
|
+
Perform exploratory data analysis on the dataset.
|
|
205
|
+
"""
|
|
206
|
+
self.first_glance.super_vision()
|
|
207
|
+
self.first_glance.check_duplicates()
|
|
208
|
+
|
|
209
|
+
def plot_target_evolution(self):
|
|
210
|
+
"""
|
|
211
|
+
Plot the target balance and evolution over time.
|
|
212
|
+
"""
|
|
213
|
+
self.visualizations.plot_target_balance()
|
|
214
|
+
self.visualizations.plot_target_evolution("scheduled_at", "min_balance_3m")
|
|
215
|
+
|
|
216
|
+
def plot_numerical_distributions(self, sub_plots: bool = False):
|
|
217
|
+
"""
|
|
218
|
+
Plot distributions of numerical columns.
|
|
219
|
+
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
sub_plots : bool, optional
|
|
223
|
+
If True, create subplots for each distribution, by default False.
|
|
224
|
+
"""
|
|
225
|
+
self.univariate_analysis.plot_distributions(
|
|
226
|
+
self.numerical_columns, grouped=sub_plots
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
def plot_categorical_cardinalities(self):
|
|
230
|
+
"""
|
|
231
|
+
Plot cardinalities of categorical columns.
|
|
232
|
+
"""
|
|
233
|
+
self.visualizations.plot_categorical_value_counts()
|
|
234
|
+
self.visualizations.visualize_high_cardinality(
|
|
235
|
+
excluded_vars=self.exclusion, id_column=self.id_column
|
|
236
|
+
)
|
|
237
|
+
self.visualizations.visualize_low_cardinality()
|
|
238
|
+
|
|
239
|
+
def plot_bivariate_numnum(self, columns: Optional[List[str]] = None):
|
|
240
|
+
"""
|
|
241
|
+
Plot bivariate analysis for numerical-numerical column pairs.
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
columns : List[str], optional
|
|
246
|
+
List of columns to include in the analysis, by default all numerical columns.
|
|
247
|
+
"""
|
|
248
|
+
if columns is None:
|
|
249
|
+
columns = []
|
|
250
|
+
self.bivariate_analysis.generate_correlation_heatmap(columns)
|
|
251
|
+
|
|
252
|
+
def plot_vif(self):
|
|
253
|
+
"""
|
|
254
|
+
Plot Variance Inflation Factor (VIF) for numerical columns.
|
|
255
|
+
"""
|
|
256
|
+
self.visualizations.plot_vif_failsafe()
|
|
257
|
+
|
|
258
|
+
def plot_numerical_repartitioning(
|
|
259
|
+
self, number_of_partitions: int, time_column: str
|
|
260
|
+
):
|
|
261
|
+
"""
|
|
262
|
+
Plot numerical feature repartitioning over time.
|
|
263
|
+
|
|
264
|
+
Parameters
|
|
265
|
+
----------
|
|
266
|
+
number_of_partitions : int
|
|
267
|
+
Number of partitions to use for binning.
|
|
268
|
+
time_column : str
|
|
269
|
+
Name of the time column.
|
|
270
|
+
"""
|
|
271
|
+
self.univariate_analysis.get_num_feature_repartition(
|
|
272
|
+
time_column, number_of_partitions
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
def print_psi(
|
|
276
|
+
self,
|
|
277
|
+
buckets: int,
|
|
278
|
+
bucket_type: Literal["quantile", "fixed_width"],
|
|
279
|
+
time_column: str,
|
|
280
|
+
time_expected: Union[str, datetime, date],
|
|
281
|
+
end_date: Union[str, datetime, date],
|
|
282
|
+
start_date: Union[str, datetime, date],
|
|
283
|
+
test_data: Optional[pd.DataFrame] = None,
|
|
284
|
+
):
|
|
285
|
+
"""
|
|
286
|
+
Print Population Stability Index (PSI) for numerical features.
|
|
287
|
+
|
|
288
|
+
Parameters
|
|
289
|
+
----------
|
|
290
|
+
buckets : int
|
|
291
|
+
Number of buckets for binning.
|
|
292
|
+
bucket_type : Literal["quantile", "fixed_width"]
|
|
293
|
+
The type of binning to use.
|
|
294
|
+
time_column : str
|
|
295
|
+
Name of the time column.
|
|
296
|
+
time_expected : Union[str, datetime, date]
|
|
297
|
+
Expected time for PSI calculation.
|
|
298
|
+
end_date : Union[str, datetime, date]
|
|
299
|
+
End date for PSI calculation.
|
|
300
|
+
start_date : Union[str, datetime, date]
|
|
301
|
+
Start date for PSI calculation.
|
|
302
|
+
test_data : Optional[pd.DataFrame], optional
|
|
303
|
+
Test dataset for PSI calculation, by default None.
|
|
304
|
+
"""
|
|
305
|
+
print("Calculating PSI with the following parameters:")
|
|
306
|
+
print(f"Time column: {time_column}")
|
|
307
|
+
print(f"Start date: {start_date}")
|
|
308
|
+
print(f"End date: {end_date}")
|
|
309
|
+
print(f"Expected time (split point): {time_expected}")
|
|
310
|
+
print(f"Number of buckets: {buckets}")
|
|
311
|
+
print(f"Bucket type: {bucket_type}")
|
|
312
|
+
print(f"Using separate test data: {'Yes' if test_data is not None else 'No'}")
|
|
313
|
+
print("=" * 60)
|
|
314
|
+
|
|
315
|
+
# Print data info before PSI calculation
|
|
316
|
+
print(f"Data shape before PSI calculation: {self.dataframe.shape}")
|
|
317
|
+
print(
|
|
318
|
+
f"Date range in data: {self.dataframe[time_column].min()} to {self.dataframe[time_column].max()}"
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
if test_data is not None:
|
|
322
|
+
print(f"Test data shape: {test_data.shape}")
|
|
323
|
+
print(
|
|
324
|
+
f"Date range in test data: {test_data[time_column].min()} to {test_data[time_column].max()}"
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
self.univariate_analysis.compute_psi(
|
|
328
|
+
time_column,
|
|
329
|
+
time_expected,
|
|
330
|
+
start_date,
|
|
331
|
+
end_date,
|
|
332
|
+
test_data,
|
|
333
|
+
buckets,
|
|
334
|
+
bucket_type,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# Print data info after PSI calculation
|
|
338
|
+
print(
|
|
339
|
+
f"Data shape after PSI calculation: {self.univariate_analysis.data.shape}"
|
|
340
|
+
)
|
|
341
|
+
print(
|
|
342
|
+
f"Date range in filtered data: {self.univariate_analysis.data[time_column].min()} to {self.univariate_analysis.data[time_column].max()}"
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
def plot_num_cat_anova(self):
|
|
346
|
+
"""
|
|
347
|
+
Plot ANOVA results for numerical-categorical column pairs.
|
|
348
|
+
"""
|
|
349
|
+
fig, _ = self.bivariate_analysis.perform_anova_numeric_categorical(
|
|
350
|
+
cat_cols=self.categorical_columns
|
|
351
|
+
)
|
|
352
|
+
fig.show()
|
|
353
|
+
|
|
354
|
+
def plot_cat_cat_cramersv(self):
|
|
355
|
+
"""
|
|
356
|
+
Plot Cramer's V for categorical-categorical column pairs.
|
|
357
|
+
"""
|
|
358
|
+
self.bivariate_analysis.plot_pairwise_cramers_v(
|
|
359
|
+
categorical_features=self.categorical_columns
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
def plot_num_univariate(self, threshold_c: float, threshold_iv: float):
|
|
363
|
+
"""
|
|
364
|
+
Plot univariate analysis for numerical columns.
|
|
365
|
+
|
|
366
|
+
Parameters
|
|
367
|
+
----------
|
|
368
|
+
threshold_c : float
|
|
369
|
+
Threshold for Cramer's V filtering.
|
|
370
|
+
threshold_iv : float
|
|
371
|
+
Threshold for Information Value filtering.
|
|
372
|
+
|
|
373
|
+
Returns
|
|
374
|
+
-------
|
|
375
|
+
Tuple[List[str], List[str]]
|
|
376
|
+
Filtered variables based on Cramer's V and Information Value.
|
|
377
|
+
"""
|
|
378
|
+
_, filtered_cramers = self.univariate_analysis.plot_cramers_v(
|
|
379
|
+
self.numerical_columns,
|
|
380
|
+
excluded_vars=self.exclusion,
|
|
381
|
+
filter_threshold=threshold_c,
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
_, filtered_iv = self.univariate_analysis.plot_information_value(
|
|
385
|
+
numerical_features=self.numerical_columns,
|
|
386
|
+
filter_threshold=threshold_iv,
|
|
387
|
+
target_column=self.target_column,
|
|
388
|
+
)
|
|
389
|
+
return filtered_cramers, filtered_iv
|
|
390
|
+
|
|
391
|
+
def impute_preview_normalization_numerics(
|
|
392
|
+
self,
|
|
393
|
+
imputation_method,
|
|
394
|
+
eliminated: Optional[List[str]] = None,
|
|
395
|
+
):
|
|
396
|
+
"""
|
|
397
|
+
Impute missing values and preview normalization for numerical columns.
|
|
398
|
+
|
|
399
|
+
Parameters
|
|
400
|
+
----------
|
|
401
|
+
imputation_method : Literal["knn", "mean", "median", "most_frequent", "quantile"]
|
|
402
|
+
Method to use for imputation.
|
|
403
|
+
eliminated : Optional[List[str]], optional
|
|
404
|
+
List of columns to eliminate, by default None.
|
|
405
|
+
"""
|
|
406
|
+
imputed = self.feature_engineering.handle_missing_values(imputation_method)
|
|
407
|
+
transforms = self.get_transformations(unwanted_features=eliminated)
|
|
408
|
+
|
|
409
|
+
EDAToolkit.save_intermediary(PATH_DATA_PROCESSED, imputed, "imputed")
|
|
410
|
+
print("Imputed dataframe saved in the processed directory.")
|
|
411
|
+
|
|
412
|
+
self.feature_engineering = FeatureEngineering(
|
|
413
|
+
imputed,
|
|
414
|
+
self.target_column,
|
|
415
|
+
self.numerical_columns,
|
|
416
|
+
self.to_be_enc,
|
|
417
|
+
transformations=transforms,
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
self.feature_engineering.diagnose_normality_transform()
|
|
421
|
+
|
|
422
|
+
def normalize_numericals(self, to_transformed):
|
|
423
|
+
"""
|
|
424
|
+
Apply normality transformations to numerical columns.
|
|
425
|
+
|
|
426
|
+
Parameters
|
|
427
|
+
----------
|
|
428
|
+
to_transformed : List[str]
|
|
429
|
+
List of columns to be transformed.
|
|
430
|
+
"""
|
|
431
|
+
transformed = self.feature_engineering.apply_normality_transformations(
|
|
432
|
+
to_transformed
|
|
433
|
+
)
|
|
434
|
+
transforms = self.get_transformations()
|
|
435
|
+
EDAToolkit.save_intermediary(PATH_DATA_PROCESSED, transformed, "transformed")
|
|
436
|
+
print("Transformed dataframe saved in the processed directory.")
|
|
437
|
+
|
|
438
|
+
self.feature_engineering = FeatureEngineering(
|
|
439
|
+
transformed,
|
|
440
|
+
self.target_column,
|
|
441
|
+
self.numerical_columns,
|
|
442
|
+
self.to_be_enc,
|
|
443
|
+
transformations=transforms,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
def process_low_cardinality_cols(
|
|
447
|
+
self,
|
|
448
|
+
handling_method: Literal[
|
|
449
|
+
"kmeans", "fixed_width", "exponential", "quantile", "equal_frequency"
|
|
450
|
+
],
|
|
451
|
+
):
|
|
452
|
+
"""
|
|
453
|
+
Process low cardinality columns.
|
|
454
|
+
|
|
455
|
+
Parameters
|
|
456
|
+
----------
|
|
457
|
+
handling_method : Literal["kmeans", "fixed_width", "exponential", "quantile", "equal_frequency"]
|
|
458
|
+
Method to use for handling low cardinality columns.
|
|
459
|
+
"""
|
|
460
|
+
binned = self.feature_engineering.binnings(methods=handling_method)
|
|
461
|
+
EDAToolkit.save_intermediary(PATH_DATA_PROCESSED, binned, "binned")
|
|
462
|
+
print(
|
|
463
|
+
"Variables with low cardinality are treated and saved in the processed directory."
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
def process_high_cardinality(
|
|
467
|
+
self,
|
|
468
|
+
selected_cols,
|
|
469
|
+
handling_method: Literal["gathering", "woe", "perlich"],
|
|
470
|
+
):
|
|
471
|
+
"""
|
|
472
|
+
Process high cardinality columns.
|
|
473
|
+
|
|
474
|
+
Parameters
|
|
475
|
+
----------
|
|
476
|
+
selected_cols : List[str]
|
|
477
|
+
List of columns to process.
|
|
478
|
+
handling_method : Literal["gathering", "woe", "perlich"]
|
|
479
|
+
Method to use for handling high cardinality columns.
|
|
480
|
+
"""
|
|
481
|
+
high_card = (
|
|
482
|
+
self.feature_engineering.transform_and_plot_high_cardinality_histograms(
|
|
483
|
+
selected_cols, method=handling_method
|
|
484
|
+
)
|
|
485
|
+
)
|
|
486
|
+
if high_card is not None:
|
|
487
|
+
EDAToolkit.save_intermediary(
|
|
488
|
+
PATH_DATA_PROCESSED, high_card, "high_cardinality_treated"
|
|
489
|
+
)
|
|
490
|
+
print(
|
|
491
|
+
"High cardinality variables are treated and dataframe saved in the processed directory."
|
|
492
|
+
)
|
|
493
|
+
transforms = self.get_transformations()
|
|
494
|
+
|
|
495
|
+
self.feature_engineering = FeatureEngineering(
|
|
496
|
+
high_card,
|
|
497
|
+
self.target_column,
|
|
498
|
+
self.numerical_columns,
|
|
499
|
+
self.to_be_enc,
|
|
500
|
+
transformations=transforms,
|
|
501
|
+
)
|
|
502
|
+
else:
|
|
503
|
+
print("High cardinality treatment failed.")
|
|
504
|
+
|
|
505
|
+
def plot_target_frequency_cols(self, scaling: bool):
|
|
506
|
+
"""
|
|
507
|
+
Plot target frequency for numerical columns.
|
|
508
|
+
|
|
509
|
+
Parameters
|
|
510
|
+
----------
|
|
511
|
+
scaling : bool
|
|
512
|
+
If True, apply scaling to the columns before plotting.
|
|
513
|
+
"""
|
|
514
|
+
self.visualizations.plot_numerical_target_frequency_line(scale=scaling)
|
|
515
|
+
|
|
516
|
+
def print_crosstab_freqs(self, num_rows):
|
|
517
|
+
"""
|
|
518
|
+
Print cross-tabulation frequencies for categorical columns.
|
|
519
|
+
|
|
520
|
+
Parameters
|
|
521
|
+
----------
|
|
522
|
+
num_rows : int
|
|
523
|
+
Number of rows to display in the output.
|
|
524
|
+
"""
|
|
525
|
+
freqs = self.visualizations.calc_cat_target_freq()
|
|
526
|
+
|
|
527
|
+
print(freqs.head(n=num_rows))
|
|
528
|
+
|
|
529
|
+
def encode_categoricals(self, method):
|
|
530
|
+
"""
|
|
531
|
+
Encode categorical columns.
|
|
532
|
+
|
|
533
|
+
Parameters
|
|
534
|
+
----------
|
|
535
|
+
method : Literal["one_hot", "distribution", "woe", "catboost"]
|
|
536
|
+
Encoding method to use.
|
|
537
|
+
"""
|
|
538
|
+
self.feature_engineering.encoding_categorical(method)
|
|
539
|
+
|
|
540
|
+
def winsorize_numericals(self, columns_to_transformed):
|
|
541
|
+
"""
|
|
542
|
+
Apply winsorization to numerical columns.
|
|
543
|
+
|
|
544
|
+
Parameters
|
|
545
|
+
----------
|
|
546
|
+
columns_to_transformed : List[str]
|
|
547
|
+
List of columns to transform.
|
|
548
|
+
"""
|
|
549
|
+
self.feature_engineering.apply_winsorization(columns_to_transformed)
|