PyIAML 1.0.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.
- iaml/__init__.py +56 -0
- iaml/actionable.py +11 -0
- iaml/actionables/__init__.py +21 -0
- iaml/actionables/boosting/__init__.py +4 -0
- iaml/actionables/boosting/act_adaboost.py +59 -0
- iaml/actionables/cleaning/__init__.py +26 -0
- iaml/actionables/cleaning/act_categorical_imputer.py +124 -0
- iaml/actionables/cleaning/act_count_vectorizer.py +204 -0
- iaml/actionables/cleaning/act_drop_categorical_column.py +51 -0
- iaml/actionables/cleaning/act_drop_date_column.py +48 -0
- iaml/actionables/cleaning/act_drop_high_cardinality_categorical.py +337 -0
- iaml/actionables/cleaning/act_drop_numerical_column.py +75 -0
- iaml/actionables/cleaning/act_drop_textual_column.py +51 -0
- iaml/actionables/cleaning/act_encode_target_column.py +56 -0
- iaml/actionables/cleaning/act_frequency_encoder.py +127 -0
- iaml/actionables/cleaning/act_hashing_vectorizer.py +186 -0
- iaml/actionables/cleaning/act_knn_imputer.py +152 -0
- iaml/actionables/cleaning/act_mean_column.py +79 -0
- iaml/actionables/cleaning/act_mice.py +464 -0
- iaml/actionables/cleaning/act_missing_count_feature.py +109 -0
- iaml/actionables/cleaning/act_missing_indicator.py +124 -0
- iaml/actionables/cleaning/act_onehot.py +65 -0
- iaml/actionables/cleaning/act_ordinal_encoder.py +177 -0
- iaml/actionables/cleaning/act_rare_category_grouper.py +173 -0
- iaml/actionables/cleaning/act_simple_imputer.py +109 -0
- iaml/actionables/cleaning/act_split_date.py +68 -0
- iaml/actionables/cleaning/act_target_encoder.py +274 -0
- iaml/actionables/cleaning/act_text_normalizer.py +241 -0
- iaml/actionables/cleaning/act_tf_idf.py +80 -0
- iaml/actionables/cleaning/act_word2vec.py +150 -0
- iaml/actionables/features_precleaning/__init__.py +12 -0
- iaml/actionables/features_precleaning/act_coerce_numeric_strings.py +194 -0
- iaml/actionables/features_precleaning/act_date_converter.py +99 -0
- iaml/actionables/features_precleaning/act_drop_bad_quality_rows.py +77 -0
- iaml/actionables/features_precleaning/act_drop_duplicate_rows.py +131 -0
- iaml/actionables/features_precleaning/act_drop_high_missing_columns.py +94 -0
- iaml/actionables/features_precleaning/act_drop_id_like_columns.py +294 -0
- iaml/actionables/features_precleaning/act_normalize_column_names.py +157 -0
- iaml/actionables/features_precleaning/act_sentinel_to_na_n.py +270 -0
- iaml/actionables/features_precleaning/act_trim_space.py +79 -0
- iaml/actionables/features_preprocessing/__init__.py +18 -0
- iaml/actionables/features_preprocessing/act_cyclical_date_encoding.py +212 -0
- iaml/actionables/features_preprocessing/act_fast_ica.py +161 -0
- iaml/actionables/features_preprocessing/act_feature_agglomeration.py +90 -0
- iaml/actionables/features_preprocessing/act_k_bins_discretizer.py +207 -0
- iaml/actionables/features_preprocessing/act_k_means_features.py +296 -0
- iaml/actionables/features_preprocessing/act_kernel_pca.py +143 -0
- iaml/actionables/features_preprocessing/act_log_transformer.py +122 -0
- iaml/actionables/features_preprocessing/act_nystroem.py +100 -0
- iaml/actionables/features_preprocessing/act_pca.py +77 -0
- iaml/actionables/features_preprocessing/act_polynomial_features.py +86 -0
- iaml/actionables/features_preprocessing/act_power_transformer.py +106 -0
- iaml/actionables/features_preprocessing/act_quantile_transformer.py +114 -0
- iaml/actionables/features_preprocessing/act_rbf_sampler.py +88 -0
- iaml/actionables/features_preprocessing/act_select_percentile.py +112 -0
- iaml/actionables/features_preprocessing/act_sparse_random_projection.py +157 -0
- iaml/actionables/features_preprocessing/act_truncated_svd.py +137 -0
- iaml/actionables/features_selection/__init__.py +8 -0
- iaml/actionables/features_selection/act_permutation_importance_selector.py +421 -0
- iaml/actionables/features_selection/act_remove_high_correlated_column.py +70 -0
- iaml/actionables/features_selection/act_remove_low_variance_column.py +74 -0
- iaml/actionables/features_selection/act_rfe.py +214 -0
- iaml/actionables/features_selection/act_select_from_model.py +325 -0
- iaml/actionables/features_selection/act_select_k_best.py +181 -0
- iaml/actionables/features_selection/act_vif_selector.py +130 -0
- iaml/actionables/imbalance/__init__.py +10 -0
- iaml/actionables/imbalance/act_adasyn.py +150 -0
- iaml/actionables/imbalance/act_borderline_smote.py +171 -0
- iaml/actionables/imbalance/act_near_miss.py +158 -0
- iaml/actionables/imbalance/act_random_over_sampling.py +60 -0
- iaml/actionables/imbalance/act_random_under_sampler.py +135 -0
- iaml/actionables/imbalance/act_smote.py +162 -0
- iaml/actionables/imbalance/act_smote_tomek.py +182 -0
- iaml/actionables/imbalance/act_smoteenn.py +193 -0
- iaml/actionables/imbalance/act_tomek_links.py +138 -0
- iaml/actionables/normalize/__init__.py +6 -0
- iaml/actionables/normalize/act_max_abs_scaler.py +78 -0
- iaml/actionables/normalize/act_minmax_scaler.py +56 -0
- iaml/actionables/normalize/act_normalizer.py +95 -0
- iaml/actionables/normalize/act_robust_scaler.py +111 -0
- iaml/actionables/normalize/act_standard_scaler.py +55 -0
- iaml/actionables/predictors/__init__.py +6 -0
- iaml/actionables/predictors/_xgboost.py +16 -0
- iaml/actionables/predictors/classifier/__init__.py +26 -0
- iaml/actionables/predictors/classifier/act_bagging_classifier.py +113 -0
- iaml/actionables/predictors/classifier/act_bernoulli_nb.py +89 -0
- iaml/actionables/predictors/classifier/act_catboost_classifier.py +135 -0
- iaml/actionables/predictors/classifier/act_complement_nb.py +106 -0
- iaml/actionables/predictors/classifier/act_decision_tree_classifier.py +117 -0
- iaml/actionables/predictors/classifier/act_extra_trees_classifier.py +115 -0
- iaml/actionables/predictors/classifier/act_gaussian_nb.py +53 -0
- iaml/actionables/predictors/classifier/act_hist_gradient_boosting_classifier.py +144 -0
- iaml/actionables/predictors/classifier/act_knn.py +86 -0
- iaml/actionables/predictors/classifier/act_light_gbm_classifier.py +211 -0
- iaml/actionables/predictors/classifier/act_linear_discriminant_analysis.py +63 -0
- iaml/actionables/predictors/classifier/act_linear_svc.py +134 -0
- iaml/actionables/predictors/classifier/act_logistic_regression.py +92 -0
- iaml/actionables/predictors/classifier/act_mlp_classifier.py +107 -0
- iaml/actionables/predictors/classifier/act_multinomial_nb.py +76 -0
- iaml/actionables/predictors/classifier/act_passive_aggressive_classifier.py +141 -0
- iaml/actionables/predictors/classifier/act_quadratic_discriminant_analysis.py +72 -0
- iaml/actionables/predictors/classifier/act_randomforest.py +113 -0
- iaml/actionables/predictors/classifier/act_ridge_classifier.py +116 -0
- iaml/actionables/predictors/classifier/act_sgd_classifier.py +149 -0
- iaml/actionables/predictors/classifier/act_svm_svc.py +88 -0
- iaml/actionables/predictors/classifier/act_xgboost.py +111 -0
- iaml/actionables/predictors/regressor/__init__.py +27 -0
- iaml/actionables/predictors/regressor/act_ada_boost_regressor.py +75 -0
- iaml/actionables/predictors/regressor/act_ard_regression.py +95 -0
- iaml/actionables/predictors/regressor/act_catboost_regressor.py +134 -0
- iaml/actionables/predictors/regressor/act_decision_tree_regressor.py +111 -0
- iaml/actionables/predictors/regressor/act_elastic_net_regressor.py +109 -0
- iaml/actionables/predictors/regressor/act_extra_trees_regressor.py +113 -0
- iaml/actionables/predictors/regressor/act_gaussian_process_regressor.py +55 -0
- iaml/actionables/predictors/regressor/act_gboost_regressor.py +95 -0
- iaml/actionables/predictors/regressor/act_hist_gradient_boosting_regressor.py +105 -0
- iaml/actionables/predictors/regressor/act_huber_regressor.py +101 -0
- iaml/actionables/predictors/regressor/act_knn_regressor.py +86 -0
- iaml/actionables/predictors/regressor/act_lasso_regressor.py +103 -0
- iaml/actionables/predictors/regressor/act_light_gbm_regressor.py +201 -0
- iaml/actionables/predictors/regressor/act_linear_regression.py +43 -0
- iaml/actionables/predictors/regressor/act_mlp_regressor.py +104 -0
- iaml/actionables/predictors/regressor/act_poisson_regressor.py +111 -0
- iaml/actionables/predictors/regressor/act_quantile_regressor.py +87 -0
- iaml/actionables/predictors/regressor/act_randomforest_regressor.py +116 -0
- iaml/actionables/predictors/regressor/act_ransac_regressor.py +106 -0
- iaml/actionables/predictors/regressor/act_ridge_regressor.py +107 -0
- iaml/actionables/predictors/regressor/act_sgd_regressor.py +106 -0
- iaml/actionables/predictors/regressor/act_svm_svr.py +81 -0
- iaml/actionables/predictors/regressor/act_xgboost_regressor.py +97 -0
- iaml/actionables/predictors/survival/__init__.py +12 -0
- iaml/actionables/predictors/survival/act_aalen_additive_model.py +83 -0
- iaml/actionables/predictors/survival/act_cox.py +110 -0
- iaml/actionables/predictors/survival/act_coxnet_survival_analysis.py +134 -0
- iaml/actionables/predictors/survival/act_extra_survival_trees.py +101 -0
- iaml/actionables/predictors/survival/act_fast_survival_svm.py +102 -0
- iaml/actionables/predictors/survival/act_gradient_boosting_survival_analysis.py +93 -0
- iaml/actionables/predictors/survival/act_random_survival_forest.py +91 -0
- iaml/actionables/predictors/survival/act_survival_component_wise_gboost.py +80 -0
- iaml/actionables/predictors/survival/act_survival_tree.py +120 -0
- iaml/actionables/predictors/survival/act_survival_xgboost.py +9 -0
- iaml/actionables/predictors/survival/act_weibull_aft.py +230 -0
- iaml/cache.py +61 -0
- iaml/cache_keys.py +57 -0
- iaml/candidate.py +736 -0
- iaml/core_dispatcher.py +125 -0
- iaml/data_type.py +11 -0
- iaml/dataset.py +506 -0
- iaml/decorators/__init__.py +3 -0
- iaml/decorators/all.py +4 -0
- iaml/decorators/is_step.py +45 -0
- iaml/decorators/runner.py +100 -0
- iaml/explanation.py +112 -0
- iaml/iaml.py +1072 -0
- iaml/iaml_pipeline.py +600 -0
- iaml/logger.py +138 -0
- iaml/meta_explorer_step.py +62 -0
- iaml/meta_ordered_step.py +28 -0
- iaml/meta_partial_explorer_step.py +34 -0
- iaml/meta_singleton.py +24 -0
- iaml/metastep.py +211 -0
- iaml/metric.py +111 -0
- iaml/metric_plot.py +82 -0
- iaml/metrics/__init__.py +21 -0
- iaml/metrics/_classification.py +28 -0
- iaml/metrics/_survival_times.py +22 -0
- iaml/metrics/accuracy_metric.py +59 -0
- iaml/metrics/balanced_accuracy_metric.py +67 -0
- iaml/metrics/brier_score.py +90 -0
- iaml/metrics/classification_error_metric.py +66 -0
- iaml/metrics/concordance_index_ipcw.py +84 -0
- iaml/metrics/concordance_index_metric.py +67 -0
- iaml/metrics/cumulative_dynamic_auc.py +119 -0
- iaml/metrics/f1_score_metric.py +71 -0
- iaml/metrics/integrated_brier_score.py +98 -0
- iaml/metrics/integrated_brier_score_loss.py +41 -0
- iaml/metrics/mean_absolute_error_metric.py +46 -0
- iaml/metrics/mean_squared_error_metric.py +46 -0
- iaml/metrics/mean_squared_log_error_metric.py +49 -0
- iaml/metrics/median_absolute_error_metric.py +48 -0
- iaml/metrics/precision_metric.py +63 -0
- iaml/metrics/r2_score_metric.py +45 -0
- iaml/metrics/recall_metric.py +65 -0
- iaml/metrics/roc_auc_metric.py +50 -0
- iaml/metrics/specificity_metric.py +44 -0
- iaml/metrics/specificity_multiclass_metric.py +55 -0
- iaml/metrics/specificity_multilabel_metric.py +60 -0
- iaml/optimizers/__init__.py +5 -0
- iaml/optimizers/bayesian_optimizer.py +193 -0
- iaml/optimizers/genetic_optimizer.py +284 -0
- iaml/optimizers/optimizer.py +31 -0
- iaml/optimizers/random_optimizer.py +101 -0
- iaml/plot.py +138 -0
- iaml/plots/__init__.py +32 -0
- iaml/plots/bar_plot.py +141 -0
- iaml/plots/box_plot.py +166 -0
- iaml/plots/class_prediction_error_plot.py +37 -0
- iaml/plots/classification_report_plot.py +35 -0
- iaml/plots/confusion_matrix_plot.py +34 -0
- iaml/plots/correlation_heatmap_plot.py +201 -0
- iaml/plots/cumulative_hazard_plot.py +72 -0
- iaml/plots/density_plot.py +210 -0
- iaml/plots/histogram_plot.py +179 -0
- iaml/plots/kaplan_meier_comparison_plot.py +89 -0
- iaml/plots/line_plot.py +70 -0
- iaml/plots/missingness_heatmap_plot.py +203 -0
- iaml/plots/outlier_plot.py +217 -0
- iaml/plots/pair_plot.py +228 -0
- iaml/plots/precision_recall_curve_plot.py +86 -0
- iaml/plots/prediction_error_plot.py +34 -0
- iaml/plots/qq_plot.py +220 -0
- iaml/plots/residual_plot.py +38 -0
- iaml/plots/roc_dynamique_curve_plot.py +79 -0
- iaml/plots/rocauc_plot.py +96 -0
- iaml/plots/shap_plot.py +187 -0
- iaml/plots/target_distribution_plot.py +241 -0
- iaml/plots/violin_plot.py +206 -0
- iaml/predictor.py +139 -0
- iaml/reference.py +65 -0
- iaml/shared_cache.py +90 -0
- iaml/sklearn_preprocessor.py +74 -0
- iaml/splitters/__init__.py +3 -0
- iaml/splitters/kfold_splitter.py +32 -0
- iaml/splitters/random_splitter.py +26 -0
- iaml/stack.py +39 -0
- iaml/statistic.py +66 -0
- iaml/statistics/__init__.py +77 -0
- iaml/statistics/anova_statistic.py +80 -0
- iaml/statistics/cardinality_ratio_statistic.py +63 -0
- iaml/statistics/category_cooccurrence_statistic.py +79 -0
- iaml/statistics/chi_square_statistic.py +81 -0
- iaml/statistics/coef_variation_statistic.py +72 -0
- iaml/statistics/correlation_with_target.py +105 -0
- iaml/statistics/count.py +72 -0
- iaml/statistics/data_type_summary_statistic.py +74 -0
- iaml/statistics/duplicate_row_statistic.py +56 -0
- iaml/statistics/effect_size_statistic.py +129 -0
- iaml/statistics/entropy_statistic.py +69 -0
- iaml/statistics/event_rate_statistic.py +52 -0
- iaml/statistics/grouped_mean_statistic.py +60 -0
- iaml/statistics/iqr_statistic.py +66 -0
- iaml/statistics/kurtosis.py +50 -0
- iaml/statistics/mad_statistic.py +66 -0
- iaml/statistics/mean.py +61 -0
- iaml/statistics/median_statistic.py +61 -0
- iaml/statistics/minmax.py +60 -0
- iaml/statistics/missing_rate_statistic.py +62 -0
- iaml/statistics/mode.py +47 -0
- iaml/statistics/most_frequent_ratio.py +81 -0
- iaml/statistics/outlier_count_iqr_statistic.py +76 -0
- iaml/statistics/quantile.py +59 -0
- iaml/statistics/range.py +53 -0
- iaml/statistics/rare_category_rate.py +92 -0
- iaml/statistics/skewness.py +53 -0
- iaml/statistics/stdev.py +50 -0
- iaml/statistics/summary_table_statistic.py +60 -0
- iaml/statistics/time_by_group_statistic.py +83 -0
- iaml/statistics/time_summary_statistic.py +56 -0
- iaml/statistics/top_k_value_counts.py +68 -0
- iaml/statistics/unique_count_statistic.py +57 -0
- iaml/statistics/value_counts.py +63 -0
- iaml/statistics/variance.py +51 -0
- iaml/statistics/violin.py +63 -0
- iaml/step.py +600 -0
- iaml/step_cache.py +87 -0
- iaml/step_wrapper.py +79 -0
- iaml/timed_pool_executor.py +492 -0
- iaml/type_of_target.py +68 -0
- iaml/void_step.py +101 -0
- iaml/worker_manager.py +169 -0
- iaml/wrapper/__init__.py +4 -0
- iaml/wrapper/wrap_basic_gridsearch.py +68 -0
- iaml/wrapper/wrap_genetic_gridsearch.py +293 -0
- iaml/wrapper/wrap_iterative_gridsearch.py +399 -0
- pyiaml-1.0.0.dist-info/METADATA +802 -0
- pyiaml-1.0.0.dist-info/RECORD +279 -0
- pyiaml-1.0.0.dist-info/WHEEL +5 -0
- pyiaml-1.0.0.dist-info/licenses/LICENSE +674 -0
- pyiaml-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""[STATISTIC] Median Absolute Deviation."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MADStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Median Absolute Deviation."""
|
|
14
|
+
|
|
15
|
+
name: str = "Median Absolute Deviation"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Median absolute deviation measures the typical absolute deviation from the median.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Median absolute deviation measures the typical absolute deviation from the median,
|
|
21
|
+
optionally per class for classification.
|
|
22
|
+
""")
|
|
23
|
+
refs: list[dict] = []
|
|
24
|
+
|
|
25
|
+
def __str__(self) -> str:
|
|
26
|
+
return 'mad'
|
|
27
|
+
|
|
28
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
29
|
+
"""Compute median absolute deviation for each numerical column."""
|
|
30
|
+
if dataset.type_of_target == 'survival':
|
|
31
|
+
return pd.DataFrame()
|
|
32
|
+
|
|
33
|
+
data = []
|
|
34
|
+
columns = []
|
|
35
|
+
|
|
36
|
+
def mad(series: pd.Series) -> float:
|
|
37
|
+
median = series.median()
|
|
38
|
+
return (series - median).abs().median()
|
|
39
|
+
|
|
40
|
+
if dataset.type_of_target == 'continuous':
|
|
41
|
+
for col in dataset.X.columns:
|
|
42
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
43
|
+
columns.append(col)
|
|
44
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
45
|
+
data.append(mad(dataset.X[col]))
|
|
46
|
+
else:
|
|
47
|
+
data.append(None)
|
|
48
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
49
|
+
|
|
50
|
+
class_labels = list(pd.unique(dataset.y))
|
|
51
|
+
for col in dataset.X.columns:
|
|
52
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
53
|
+
for label in ['all'] + class_labels:
|
|
54
|
+
columns.append(f"{col}_{label}")
|
|
55
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
56
|
+
if label == 'all':
|
|
57
|
+
data.append(mad(dataset.X[col]))
|
|
58
|
+
else:
|
|
59
|
+
data.append(mad(dataset.X.loc[dataset.y == label][col]))
|
|
60
|
+
else:
|
|
61
|
+
data.append(None)
|
|
62
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
63
|
+
|
|
64
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
65
|
+
"""Does this statistic apply to the dataset?"""
|
|
66
|
+
return dataset.type_of_target != 'survival'
|
iaml/statistics/mean.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""[STATISTIC] Mean."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MeanStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Mean."""
|
|
14
|
+
|
|
15
|
+
name: str = "Mean"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Mean measures the average of numerical columns.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Mean measures the average of numerical columns, optionally per class for classification.
|
|
21
|
+
""")
|
|
22
|
+
refs: list[dict] = []
|
|
23
|
+
|
|
24
|
+
def __str__(self) -> str:
|
|
25
|
+
return 'mean'
|
|
26
|
+
|
|
27
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
28
|
+
"""Compute mean for each numerical column."""
|
|
29
|
+
if dataset.type_of_target == 'survival':
|
|
30
|
+
return pd.DataFrame()
|
|
31
|
+
|
|
32
|
+
data = []
|
|
33
|
+
columns = []
|
|
34
|
+
|
|
35
|
+
if dataset.type_of_target == 'continuous':
|
|
36
|
+
for col in dataset.X.columns:
|
|
37
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
38
|
+
columns.append(col)
|
|
39
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
40
|
+
data.append(dataset.X[col].mean())
|
|
41
|
+
else:
|
|
42
|
+
data.append(None)
|
|
43
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
44
|
+
|
|
45
|
+
class_labels = list(pd.unique(dataset.y))
|
|
46
|
+
for col in dataset.X.columns:
|
|
47
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
48
|
+
for label in ['all'] + class_labels:
|
|
49
|
+
columns.append(f"{col}_{label}")
|
|
50
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
51
|
+
if label == 'all':
|
|
52
|
+
data.append(dataset.X[col].mean())
|
|
53
|
+
else:
|
|
54
|
+
data.append(dataset.X.loc[dataset.y == label][col].mean())
|
|
55
|
+
else:
|
|
56
|
+
data.append(None)
|
|
57
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
58
|
+
|
|
59
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
60
|
+
"""Does this statistic apply to the dataset?"""
|
|
61
|
+
return dataset.type_of_target != 'survival'
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""[STATISTIC] Median."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MedianStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Median."""
|
|
14
|
+
|
|
15
|
+
name: str = "Median"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Median measures the central value of numerical columns.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Median measures the central value of numerical columns, per class for classification.
|
|
21
|
+
""")
|
|
22
|
+
refs: list[dict] = []
|
|
23
|
+
|
|
24
|
+
def __str__(self) -> str:
|
|
25
|
+
return 'median'
|
|
26
|
+
|
|
27
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
28
|
+
"""Compute median for each numerical column."""
|
|
29
|
+
if dataset.type_of_target == 'survival':
|
|
30
|
+
return pd.DataFrame()
|
|
31
|
+
|
|
32
|
+
data = []
|
|
33
|
+
columns = []
|
|
34
|
+
|
|
35
|
+
if dataset.type_of_target == 'continuous':
|
|
36
|
+
for col in dataset.X.columns:
|
|
37
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
38
|
+
columns.append(col)
|
|
39
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
40
|
+
data.append(dataset.X[col].median())
|
|
41
|
+
else:
|
|
42
|
+
data.append(None)
|
|
43
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
44
|
+
|
|
45
|
+
class_labels = list(pd.unique(dataset.y))
|
|
46
|
+
for col in dataset.X.columns:
|
|
47
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
48
|
+
for label in ['all'] + class_labels:
|
|
49
|
+
columns.append(f"{col}_{label}")
|
|
50
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
51
|
+
if label == 'all':
|
|
52
|
+
data.append(dataset.X[col].median())
|
|
53
|
+
else:
|
|
54
|
+
data.append(dataset.X.loc[dataset.y == label][col].median())
|
|
55
|
+
else:
|
|
56
|
+
data.append(None)
|
|
57
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
58
|
+
|
|
59
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
60
|
+
"""Does this statistic apply to the dataset?"""
|
|
61
|
+
return dataset.type_of_target != 'survival'
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""[STATISTIC] Min / Max."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BoundStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Bound."""
|
|
14
|
+
|
|
15
|
+
name: str = "Bound"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Bound measures extreme values (min/max) of numerical columns.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Bound measures extreme values (min/max) of numerical columns, per class for classification.
|
|
21
|
+
""")
|
|
22
|
+
refs: list[dict] = []
|
|
23
|
+
|
|
24
|
+
bound_to_compute = ['min', 'max']
|
|
25
|
+
|
|
26
|
+
def __init__(self, bound: str = 'min') -> None:
|
|
27
|
+
self.bound = bound
|
|
28
|
+
|
|
29
|
+
def __str__(self) -> str:
|
|
30
|
+
return self.bound
|
|
31
|
+
|
|
32
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
33
|
+
"""Compute min/max for numerical columns."""
|
|
34
|
+
if dataset.type_of_target in ['survival', 'continuous']:
|
|
35
|
+
return pd.DataFrame()
|
|
36
|
+
|
|
37
|
+
class_labels = list(pd.unique(dataset.y))
|
|
38
|
+
df = pd.DataFrame()
|
|
39
|
+
for bound in BoundStatistic.bound_to_compute:
|
|
40
|
+
self.bound = bound
|
|
41
|
+
data = []
|
|
42
|
+
columns = []
|
|
43
|
+
for col in dataset.X.columns:
|
|
44
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
45
|
+
for label in ['all'] + class_labels:
|
|
46
|
+
columns.append(f"{col}_{label}")
|
|
47
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
48
|
+
if label == 'all':
|
|
49
|
+
value = getattr(dataset.X[col], bound)()
|
|
50
|
+
else:
|
|
51
|
+
value = getattr(dataset.X.loc[dataset.y == label][col], bound)()
|
|
52
|
+
data.append(value)
|
|
53
|
+
else:
|
|
54
|
+
data.append(None)
|
|
55
|
+
df = pd.concat([df, pd.DataFrame([data], index=[str(self)], columns=columns)])
|
|
56
|
+
return df
|
|
57
|
+
|
|
58
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
59
|
+
"""Does this statistic apply to the dataset?"""
|
|
60
|
+
return dataset.type_of_target not in ['survival', 'continuous']
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""[STATISTIC] Missing Rate."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MissingRateStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Missing Rate."""
|
|
14
|
+
|
|
15
|
+
name: str = "Missing Rate"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Missing rate measures the percentage of missing values per column.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Missing rate measures the percentage of missing values per column,
|
|
21
|
+
optionally per class for classification.
|
|
22
|
+
""")
|
|
23
|
+
refs: list[dict] = []
|
|
24
|
+
|
|
25
|
+
def __str__(self) -> str:
|
|
26
|
+
return 'missing_rate'
|
|
27
|
+
|
|
28
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
29
|
+
"""Compute missing rate for each column."""
|
|
30
|
+
if dataset.type_of_target == 'survival':
|
|
31
|
+
return pd.DataFrame()
|
|
32
|
+
|
|
33
|
+
data = []
|
|
34
|
+
columns = []
|
|
35
|
+
|
|
36
|
+
if dataset.type_of_target == 'continuous':
|
|
37
|
+
for col in dataset.X.columns:
|
|
38
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
39
|
+
columns.append(col)
|
|
40
|
+
values = dataset.X[col]
|
|
41
|
+
n_rows = int(values.shape[0])
|
|
42
|
+
rate = values.isna().mean() if n_rows else 0.0
|
|
43
|
+
data.append(rate)
|
|
44
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
45
|
+
|
|
46
|
+
class_labels = list(pd.unique(dataset.y))
|
|
47
|
+
for col in dataset.X.columns:
|
|
48
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
49
|
+
for label in ['all'] + class_labels:
|
|
50
|
+
columns.append(f"{col}_{label}")
|
|
51
|
+
if label == 'all':
|
|
52
|
+
values = dataset.X[col]
|
|
53
|
+
else:
|
|
54
|
+
values = dataset.X.loc[dataset.y == label][col]
|
|
55
|
+
n_rows = int(values.shape[0])
|
|
56
|
+
rate = values.isna().mean() if n_rows else 0.0
|
|
57
|
+
data.append(rate)
|
|
58
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
59
|
+
|
|
60
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
61
|
+
"""Does this statistic apply to the dataset?"""
|
|
62
|
+
return dataset.type_of_target != 'survival'
|
iaml/statistics/mode.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""[STATISTIC] Mode."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ModeStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Mode."""
|
|
14
|
+
|
|
15
|
+
name: str = "Mode"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Mode measures the most common values of each column.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Mode measures the most common values of each column, per class for classification.
|
|
21
|
+
""")
|
|
22
|
+
refs: list[dict] = []
|
|
23
|
+
|
|
24
|
+
def __str__(self) -> str:
|
|
25
|
+
return 'mode'
|
|
26
|
+
|
|
27
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
28
|
+
"""Compute mode for each column."""
|
|
29
|
+
if dataset.type_of_target in ['survival', 'continuous']:
|
|
30
|
+
return pd.DataFrame()
|
|
31
|
+
|
|
32
|
+
class_labels = list(pd.unique(dataset.y))
|
|
33
|
+
data = []
|
|
34
|
+
columns = []
|
|
35
|
+
for col in dataset.X.columns:
|
|
36
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
37
|
+
for label in ['all'] + class_labels:
|
|
38
|
+
columns.append(f"{col}_{label}")
|
|
39
|
+
if label == 'all':
|
|
40
|
+
data.append(dataset.X[col].mode().to_list())
|
|
41
|
+
else:
|
|
42
|
+
data.append(dataset.X.loc[dataset.y == label][col].mode().to_list())
|
|
43
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
44
|
+
|
|
45
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
46
|
+
"""Does this statistic apply to the dataset?"""
|
|
47
|
+
return dataset.type_of_target not in ['survival', 'continuous']
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""[STATISTIC] Most Frequent Ratio."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MostFrequentRatioStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Most Frequent Ratio."""
|
|
14
|
+
|
|
15
|
+
name: str = "Most Frequent Ratio"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Most frequent ratio measures the share of the dominant category in
|
|
18
|
+
categorical columns.
|
|
19
|
+
""")
|
|
20
|
+
_description_long: str = textwrap.dedent("""\
|
|
21
|
+
Most frequent ratio measures the ratio of the most common category in
|
|
22
|
+
categorical columns, optionally per class.
|
|
23
|
+
""")
|
|
24
|
+
refs: list[dict] = []
|
|
25
|
+
|
|
26
|
+
def __str__(self) -> str:
|
|
27
|
+
return 'most_frequent_ratio'
|
|
28
|
+
|
|
29
|
+
def _select_columns(self, dataset: Dataset) -> list[str]:
|
|
30
|
+
columns = dataset.get_columns_names_by_type(DataType.CATEGORICAL)
|
|
31
|
+
category_columns = list(dataset.X.select_dtypes(include=['category']).columns)
|
|
32
|
+
seen = set()
|
|
33
|
+
ordered = []
|
|
34
|
+
for column in columns + category_columns:
|
|
35
|
+
if column in dataset.X.columns and column not in seen:
|
|
36
|
+
ordered.append(column)
|
|
37
|
+
seen.add(column)
|
|
38
|
+
return ordered
|
|
39
|
+
|
|
40
|
+
def _most_frequent_ratio(self, series: pd.Series) -> float:
|
|
41
|
+
counts = series.value_counts(dropna=True)
|
|
42
|
+
if counts.empty:
|
|
43
|
+
return 0.0
|
|
44
|
+
total = int(counts.sum())
|
|
45
|
+
if total <= 0:
|
|
46
|
+
return 0.0
|
|
47
|
+
top = int(counts.max())
|
|
48
|
+
return top / total
|
|
49
|
+
|
|
50
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
51
|
+
"""Compute most frequent ratio for categorical columns."""
|
|
52
|
+
if dataset.type_of_target == 'survival':
|
|
53
|
+
return pd.DataFrame()
|
|
54
|
+
|
|
55
|
+
columns = self._select_columns(dataset)
|
|
56
|
+
if not columns:
|
|
57
|
+
return pd.DataFrame()
|
|
58
|
+
|
|
59
|
+
data = []
|
|
60
|
+
df_columns = []
|
|
61
|
+
|
|
62
|
+
if dataset.type_of_target == 'continuous':
|
|
63
|
+
for col in columns:
|
|
64
|
+
df_columns.append(col)
|
|
65
|
+
data.append(self._most_frequent_ratio(dataset.X[col]))
|
|
66
|
+
return pd.DataFrame([data], index=[str(self)], columns=df_columns)
|
|
67
|
+
|
|
68
|
+
class_labels = list(pd.unique(dataset.y))
|
|
69
|
+
for col in columns:
|
|
70
|
+
for label in ['all'] + class_labels:
|
|
71
|
+
df_columns.append(f"{col}_{label}")
|
|
72
|
+
if label == 'all':
|
|
73
|
+
values = dataset.X[col]
|
|
74
|
+
else:
|
|
75
|
+
values = dataset.X.loc[dataset.y == label][col]
|
|
76
|
+
data.append(self._most_frequent_ratio(values))
|
|
77
|
+
return pd.DataFrame([data], index=[str(self)], columns=df_columns)
|
|
78
|
+
|
|
79
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
80
|
+
"""Does this statistic apply to the dataset?"""
|
|
81
|
+
return dataset.type_of_target != 'survival'
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""[STATISTIC] Outlier Count (IQR)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class OutlierCountIQRStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Outlier Count (IQR)."""
|
|
14
|
+
|
|
15
|
+
name: str = "Outlier Count (IQR)"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Outlier count measures how many values fall outside 1.5*IQR.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Outlier count measures how many values fall outside 1.5*IQR,
|
|
21
|
+
optionally per class for classification.
|
|
22
|
+
""")
|
|
23
|
+
refs: list[dict] = []
|
|
24
|
+
|
|
25
|
+
def __str__(self) -> str:
|
|
26
|
+
return 'outlier_count_iqr'
|
|
27
|
+
|
|
28
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
29
|
+
"""Compute outlier counts (1.5*IQR rule) for each numerical column."""
|
|
30
|
+
if dataset.type_of_target == 'survival':
|
|
31
|
+
return pd.DataFrame()
|
|
32
|
+
|
|
33
|
+
def count_outliers(values: pd.Series) -> int:
|
|
34
|
+
values = values.dropna()
|
|
35
|
+
if values.empty:
|
|
36
|
+
return 0
|
|
37
|
+
q1 = values.quantile(0.25)
|
|
38
|
+
q3 = values.quantile(0.75)
|
|
39
|
+
iqr = q3 - q1
|
|
40
|
+
if pd.isna(iqr):
|
|
41
|
+
return 0
|
|
42
|
+
lower = q1 - 1.5 * iqr
|
|
43
|
+
upper = q3 + 1.5 * iqr
|
|
44
|
+
return int(((values < lower) | (values > upper)).sum())
|
|
45
|
+
|
|
46
|
+
data = []
|
|
47
|
+
columns = []
|
|
48
|
+
|
|
49
|
+
if dataset.type_of_target == 'continuous':
|
|
50
|
+
for col in dataset.X.columns:
|
|
51
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
52
|
+
columns.append(col)
|
|
53
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
54
|
+
data.append(count_outliers(dataset.X[col]))
|
|
55
|
+
else:
|
|
56
|
+
data.append(None)
|
|
57
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
58
|
+
|
|
59
|
+
class_labels = list(pd.unique(dataset.y))
|
|
60
|
+
for col in dataset.X.columns:
|
|
61
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
62
|
+
for label in ['all'] + class_labels:
|
|
63
|
+
columns.append(f"{col}_{label}")
|
|
64
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
65
|
+
if label == 'all':
|
|
66
|
+
values = dataset.X[col]
|
|
67
|
+
else:
|
|
68
|
+
values = dataset.X.loc[dataset.y == label][col]
|
|
69
|
+
data.append(count_outliers(values))
|
|
70
|
+
else:
|
|
71
|
+
data.append(None)
|
|
72
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
73
|
+
|
|
74
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
75
|
+
"""Does this statistic apply to the dataset?"""
|
|
76
|
+
return dataset.type_of_target != 'survival'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""[STATISTIC] Quantile."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class QuantileStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Quantile."""
|
|
14
|
+
|
|
15
|
+
name: str = "Quantile"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Quantile measures percentile values of numerical columns.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Quantile measures percentile values of numerical columns, per class for classification.
|
|
21
|
+
""")
|
|
22
|
+
refs: list[dict] = []
|
|
23
|
+
|
|
24
|
+
quantile_to_compute = [0.1, 0.25, 0.50, 0.75, 0.90]
|
|
25
|
+
|
|
26
|
+
def __init__(self, percentile: float = 0.5) -> None:
|
|
27
|
+
self.percentile = percentile
|
|
28
|
+
|
|
29
|
+
def __str__(self) -> str:
|
|
30
|
+
return f'quantile_{self.percentile}'
|
|
31
|
+
|
|
32
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
33
|
+
"""Compute quantiles for numerical columns."""
|
|
34
|
+
if dataset.type_of_target in ['survival', 'continuous']:
|
|
35
|
+
return pd.DataFrame()
|
|
36
|
+
|
|
37
|
+
class_labels = list(pd.unique(dataset.y))
|
|
38
|
+
df = pd.DataFrame()
|
|
39
|
+
for quantile in QuantileStatistic.quantile_to_compute:
|
|
40
|
+
self.percentile = quantile
|
|
41
|
+
data = []
|
|
42
|
+
columns = []
|
|
43
|
+
for col in dataset.X.columns:
|
|
44
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
45
|
+
for label in ['all'] + class_labels:
|
|
46
|
+
columns.append(f"{col}_{label}")
|
|
47
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
48
|
+
if label == 'all':
|
|
49
|
+
data.append(dataset.X[col].quantile(self.percentile))
|
|
50
|
+
else:
|
|
51
|
+
data.append(dataset.X.loc[dataset.y == label][col].quantile(self.percentile))
|
|
52
|
+
else:
|
|
53
|
+
data.append(None)
|
|
54
|
+
df = pd.concat([df, pd.DataFrame([data], index=[str(self)], columns=columns)])
|
|
55
|
+
return df
|
|
56
|
+
|
|
57
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
58
|
+
"""Does this statistic apply to the dataset?"""
|
|
59
|
+
return dataset.type_of_target not in ['survival', 'continuous']
|
iaml/statistics/range.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""[STATISTIC] Range."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from ..dataset import Dataset
|
|
8
|
+
from ..data_type import DataType
|
|
9
|
+
from ..statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RangeStatistic(Statistic):
|
|
13
|
+
"""[STATISTIC] Range."""
|
|
14
|
+
|
|
15
|
+
name: str = "Range"
|
|
16
|
+
_description: str = textwrap.dedent("""\
|
|
17
|
+
Range measures the dispersion between min and max for numerical columns.
|
|
18
|
+
""")
|
|
19
|
+
_description_long: str = textwrap.dedent("""\
|
|
20
|
+
Range measures the dispersion between min and max for numerical columns,
|
|
21
|
+
per class for classification.
|
|
22
|
+
""")
|
|
23
|
+
refs: list[dict] = []
|
|
24
|
+
|
|
25
|
+
def __str__(self) -> str:
|
|
26
|
+
return 'range'
|
|
27
|
+
|
|
28
|
+
def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
|
|
29
|
+
"""Compute range for numerical columns."""
|
|
30
|
+
if dataset.type_of_target in ['survival', 'continuous']:
|
|
31
|
+
return pd.DataFrame()
|
|
32
|
+
|
|
33
|
+
class_labels = list(pd.unique(dataset.y))
|
|
34
|
+
data = []
|
|
35
|
+
columns = []
|
|
36
|
+
for col in dataset.X.columns:
|
|
37
|
+
if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
|
|
38
|
+
for label in ['all'] + class_labels:
|
|
39
|
+
columns.append(f"{col}_{label}")
|
|
40
|
+
if dataset.columns_types[col][1] == DataType.NUMERIC:
|
|
41
|
+
if label == 'all':
|
|
42
|
+
value = dataset.X[col].max() - dataset.X[col].min()
|
|
43
|
+
else:
|
|
44
|
+
values = dataset.X.loc[dataset.y == label][col]
|
|
45
|
+
value = values.max() - values.min()
|
|
46
|
+
data.append(value)
|
|
47
|
+
else:
|
|
48
|
+
data.append(None)
|
|
49
|
+
return pd.DataFrame([data], index=[str(self)], columns=columns)
|
|
50
|
+
|
|
51
|
+
def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
|
|
52
|
+
"""Does this statistic apply to the dataset?"""
|
|
53
|
+
return dataset.type_of_target not in ['survival', 'continuous']
|