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.
Files changed (279) hide show
  1. iaml/__init__.py +56 -0
  2. iaml/actionable.py +11 -0
  3. iaml/actionables/__init__.py +21 -0
  4. iaml/actionables/boosting/__init__.py +4 -0
  5. iaml/actionables/boosting/act_adaboost.py +59 -0
  6. iaml/actionables/cleaning/__init__.py +26 -0
  7. iaml/actionables/cleaning/act_categorical_imputer.py +124 -0
  8. iaml/actionables/cleaning/act_count_vectorizer.py +204 -0
  9. iaml/actionables/cleaning/act_drop_categorical_column.py +51 -0
  10. iaml/actionables/cleaning/act_drop_date_column.py +48 -0
  11. iaml/actionables/cleaning/act_drop_high_cardinality_categorical.py +337 -0
  12. iaml/actionables/cleaning/act_drop_numerical_column.py +75 -0
  13. iaml/actionables/cleaning/act_drop_textual_column.py +51 -0
  14. iaml/actionables/cleaning/act_encode_target_column.py +56 -0
  15. iaml/actionables/cleaning/act_frequency_encoder.py +127 -0
  16. iaml/actionables/cleaning/act_hashing_vectorizer.py +186 -0
  17. iaml/actionables/cleaning/act_knn_imputer.py +152 -0
  18. iaml/actionables/cleaning/act_mean_column.py +79 -0
  19. iaml/actionables/cleaning/act_mice.py +464 -0
  20. iaml/actionables/cleaning/act_missing_count_feature.py +109 -0
  21. iaml/actionables/cleaning/act_missing_indicator.py +124 -0
  22. iaml/actionables/cleaning/act_onehot.py +65 -0
  23. iaml/actionables/cleaning/act_ordinal_encoder.py +177 -0
  24. iaml/actionables/cleaning/act_rare_category_grouper.py +173 -0
  25. iaml/actionables/cleaning/act_simple_imputer.py +109 -0
  26. iaml/actionables/cleaning/act_split_date.py +68 -0
  27. iaml/actionables/cleaning/act_target_encoder.py +274 -0
  28. iaml/actionables/cleaning/act_text_normalizer.py +241 -0
  29. iaml/actionables/cleaning/act_tf_idf.py +80 -0
  30. iaml/actionables/cleaning/act_word2vec.py +150 -0
  31. iaml/actionables/features_precleaning/__init__.py +12 -0
  32. iaml/actionables/features_precleaning/act_coerce_numeric_strings.py +194 -0
  33. iaml/actionables/features_precleaning/act_date_converter.py +99 -0
  34. iaml/actionables/features_precleaning/act_drop_bad_quality_rows.py +77 -0
  35. iaml/actionables/features_precleaning/act_drop_duplicate_rows.py +131 -0
  36. iaml/actionables/features_precleaning/act_drop_high_missing_columns.py +94 -0
  37. iaml/actionables/features_precleaning/act_drop_id_like_columns.py +294 -0
  38. iaml/actionables/features_precleaning/act_normalize_column_names.py +157 -0
  39. iaml/actionables/features_precleaning/act_sentinel_to_na_n.py +270 -0
  40. iaml/actionables/features_precleaning/act_trim_space.py +79 -0
  41. iaml/actionables/features_preprocessing/__init__.py +18 -0
  42. iaml/actionables/features_preprocessing/act_cyclical_date_encoding.py +212 -0
  43. iaml/actionables/features_preprocessing/act_fast_ica.py +161 -0
  44. iaml/actionables/features_preprocessing/act_feature_agglomeration.py +90 -0
  45. iaml/actionables/features_preprocessing/act_k_bins_discretizer.py +207 -0
  46. iaml/actionables/features_preprocessing/act_k_means_features.py +296 -0
  47. iaml/actionables/features_preprocessing/act_kernel_pca.py +143 -0
  48. iaml/actionables/features_preprocessing/act_log_transformer.py +122 -0
  49. iaml/actionables/features_preprocessing/act_nystroem.py +100 -0
  50. iaml/actionables/features_preprocessing/act_pca.py +77 -0
  51. iaml/actionables/features_preprocessing/act_polynomial_features.py +86 -0
  52. iaml/actionables/features_preprocessing/act_power_transformer.py +106 -0
  53. iaml/actionables/features_preprocessing/act_quantile_transformer.py +114 -0
  54. iaml/actionables/features_preprocessing/act_rbf_sampler.py +88 -0
  55. iaml/actionables/features_preprocessing/act_select_percentile.py +112 -0
  56. iaml/actionables/features_preprocessing/act_sparse_random_projection.py +157 -0
  57. iaml/actionables/features_preprocessing/act_truncated_svd.py +137 -0
  58. iaml/actionables/features_selection/__init__.py +8 -0
  59. iaml/actionables/features_selection/act_permutation_importance_selector.py +421 -0
  60. iaml/actionables/features_selection/act_remove_high_correlated_column.py +70 -0
  61. iaml/actionables/features_selection/act_remove_low_variance_column.py +74 -0
  62. iaml/actionables/features_selection/act_rfe.py +214 -0
  63. iaml/actionables/features_selection/act_select_from_model.py +325 -0
  64. iaml/actionables/features_selection/act_select_k_best.py +181 -0
  65. iaml/actionables/features_selection/act_vif_selector.py +130 -0
  66. iaml/actionables/imbalance/__init__.py +10 -0
  67. iaml/actionables/imbalance/act_adasyn.py +150 -0
  68. iaml/actionables/imbalance/act_borderline_smote.py +171 -0
  69. iaml/actionables/imbalance/act_near_miss.py +158 -0
  70. iaml/actionables/imbalance/act_random_over_sampling.py +60 -0
  71. iaml/actionables/imbalance/act_random_under_sampler.py +135 -0
  72. iaml/actionables/imbalance/act_smote.py +162 -0
  73. iaml/actionables/imbalance/act_smote_tomek.py +182 -0
  74. iaml/actionables/imbalance/act_smoteenn.py +193 -0
  75. iaml/actionables/imbalance/act_tomek_links.py +138 -0
  76. iaml/actionables/normalize/__init__.py +6 -0
  77. iaml/actionables/normalize/act_max_abs_scaler.py +78 -0
  78. iaml/actionables/normalize/act_minmax_scaler.py +56 -0
  79. iaml/actionables/normalize/act_normalizer.py +95 -0
  80. iaml/actionables/normalize/act_robust_scaler.py +111 -0
  81. iaml/actionables/normalize/act_standard_scaler.py +55 -0
  82. iaml/actionables/predictors/__init__.py +6 -0
  83. iaml/actionables/predictors/_xgboost.py +16 -0
  84. iaml/actionables/predictors/classifier/__init__.py +26 -0
  85. iaml/actionables/predictors/classifier/act_bagging_classifier.py +113 -0
  86. iaml/actionables/predictors/classifier/act_bernoulli_nb.py +89 -0
  87. iaml/actionables/predictors/classifier/act_catboost_classifier.py +135 -0
  88. iaml/actionables/predictors/classifier/act_complement_nb.py +106 -0
  89. iaml/actionables/predictors/classifier/act_decision_tree_classifier.py +117 -0
  90. iaml/actionables/predictors/classifier/act_extra_trees_classifier.py +115 -0
  91. iaml/actionables/predictors/classifier/act_gaussian_nb.py +53 -0
  92. iaml/actionables/predictors/classifier/act_hist_gradient_boosting_classifier.py +144 -0
  93. iaml/actionables/predictors/classifier/act_knn.py +86 -0
  94. iaml/actionables/predictors/classifier/act_light_gbm_classifier.py +211 -0
  95. iaml/actionables/predictors/classifier/act_linear_discriminant_analysis.py +63 -0
  96. iaml/actionables/predictors/classifier/act_linear_svc.py +134 -0
  97. iaml/actionables/predictors/classifier/act_logistic_regression.py +92 -0
  98. iaml/actionables/predictors/classifier/act_mlp_classifier.py +107 -0
  99. iaml/actionables/predictors/classifier/act_multinomial_nb.py +76 -0
  100. iaml/actionables/predictors/classifier/act_passive_aggressive_classifier.py +141 -0
  101. iaml/actionables/predictors/classifier/act_quadratic_discriminant_analysis.py +72 -0
  102. iaml/actionables/predictors/classifier/act_randomforest.py +113 -0
  103. iaml/actionables/predictors/classifier/act_ridge_classifier.py +116 -0
  104. iaml/actionables/predictors/classifier/act_sgd_classifier.py +149 -0
  105. iaml/actionables/predictors/classifier/act_svm_svc.py +88 -0
  106. iaml/actionables/predictors/classifier/act_xgboost.py +111 -0
  107. iaml/actionables/predictors/regressor/__init__.py +27 -0
  108. iaml/actionables/predictors/regressor/act_ada_boost_regressor.py +75 -0
  109. iaml/actionables/predictors/regressor/act_ard_regression.py +95 -0
  110. iaml/actionables/predictors/regressor/act_catboost_regressor.py +134 -0
  111. iaml/actionables/predictors/regressor/act_decision_tree_regressor.py +111 -0
  112. iaml/actionables/predictors/regressor/act_elastic_net_regressor.py +109 -0
  113. iaml/actionables/predictors/regressor/act_extra_trees_regressor.py +113 -0
  114. iaml/actionables/predictors/regressor/act_gaussian_process_regressor.py +55 -0
  115. iaml/actionables/predictors/regressor/act_gboost_regressor.py +95 -0
  116. iaml/actionables/predictors/regressor/act_hist_gradient_boosting_regressor.py +105 -0
  117. iaml/actionables/predictors/regressor/act_huber_regressor.py +101 -0
  118. iaml/actionables/predictors/regressor/act_knn_regressor.py +86 -0
  119. iaml/actionables/predictors/regressor/act_lasso_regressor.py +103 -0
  120. iaml/actionables/predictors/regressor/act_light_gbm_regressor.py +201 -0
  121. iaml/actionables/predictors/regressor/act_linear_regression.py +43 -0
  122. iaml/actionables/predictors/regressor/act_mlp_regressor.py +104 -0
  123. iaml/actionables/predictors/regressor/act_poisson_regressor.py +111 -0
  124. iaml/actionables/predictors/regressor/act_quantile_regressor.py +87 -0
  125. iaml/actionables/predictors/regressor/act_randomforest_regressor.py +116 -0
  126. iaml/actionables/predictors/regressor/act_ransac_regressor.py +106 -0
  127. iaml/actionables/predictors/regressor/act_ridge_regressor.py +107 -0
  128. iaml/actionables/predictors/regressor/act_sgd_regressor.py +106 -0
  129. iaml/actionables/predictors/regressor/act_svm_svr.py +81 -0
  130. iaml/actionables/predictors/regressor/act_xgboost_regressor.py +97 -0
  131. iaml/actionables/predictors/survival/__init__.py +12 -0
  132. iaml/actionables/predictors/survival/act_aalen_additive_model.py +83 -0
  133. iaml/actionables/predictors/survival/act_cox.py +110 -0
  134. iaml/actionables/predictors/survival/act_coxnet_survival_analysis.py +134 -0
  135. iaml/actionables/predictors/survival/act_extra_survival_trees.py +101 -0
  136. iaml/actionables/predictors/survival/act_fast_survival_svm.py +102 -0
  137. iaml/actionables/predictors/survival/act_gradient_boosting_survival_analysis.py +93 -0
  138. iaml/actionables/predictors/survival/act_random_survival_forest.py +91 -0
  139. iaml/actionables/predictors/survival/act_survival_component_wise_gboost.py +80 -0
  140. iaml/actionables/predictors/survival/act_survival_tree.py +120 -0
  141. iaml/actionables/predictors/survival/act_survival_xgboost.py +9 -0
  142. iaml/actionables/predictors/survival/act_weibull_aft.py +230 -0
  143. iaml/cache.py +61 -0
  144. iaml/cache_keys.py +57 -0
  145. iaml/candidate.py +736 -0
  146. iaml/core_dispatcher.py +125 -0
  147. iaml/data_type.py +11 -0
  148. iaml/dataset.py +506 -0
  149. iaml/decorators/__init__.py +3 -0
  150. iaml/decorators/all.py +4 -0
  151. iaml/decorators/is_step.py +45 -0
  152. iaml/decorators/runner.py +100 -0
  153. iaml/explanation.py +112 -0
  154. iaml/iaml.py +1072 -0
  155. iaml/iaml_pipeline.py +600 -0
  156. iaml/logger.py +138 -0
  157. iaml/meta_explorer_step.py +62 -0
  158. iaml/meta_ordered_step.py +28 -0
  159. iaml/meta_partial_explorer_step.py +34 -0
  160. iaml/meta_singleton.py +24 -0
  161. iaml/metastep.py +211 -0
  162. iaml/metric.py +111 -0
  163. iaml/metric_plot.py +82 -0
  164. iaml/metrics/__init__.py +21 -0
  165. iaml/metrics/_classification.py +28 -0
  166. iaml/metrics/_survival_times.py +22 -0
  167. iaml/metrics/accuracy_metric.py +59 -0
  168. iaml/metrics/balanced_accuracy_metric.py +67 -0
  169. iaml/metrics/brier_score.py +90 -0
  170. iaml/metrics/classification_error_metric.py +66 -0
  171. iaml/metrics/concordance_index_ipcw.py +84 -0
  172. iaml/metrics/concordance_index_metric.py +67 -0
  173. iaml/metrics/cumulative_dynamic_auc.py +119 -0
  174. iaml/metrics/f1_score_metric.py +71 -0
  175. iaml/metrics/integrated_brier_score.py +98 -0
  176. iaml/metrics/integrated_brier_score_loss.py +41 -0
  177. iaml/metrics/mean_absolute_error_metric.py +46 -0
  178. iaml/metrics/mean_squared_error_metric.py +46 -0
  179. iaml/metrics/mean_squared_log_error_metric.py +49 -0
  180. iaml/metrics/median_absolute_error_metric.py +48 -0
  181. iaml/metrics/precision_metric.py +63 -0
  182. iaml/metrics/r2_score_metric.py +45 -0
  183. iaml/metrics/recall_metric.py +65 -0
  184. iaml/metrics/roc_auc_metric.py +50 -0
  185. iaml/metrics/specificity_metric.py +44 -0
  186. iaml/metrics/specificity_multiclass_metric.py +55 -0
  187. iaml/metrics/specificity_multilabel_metric.py +60 -0
  188. iaml/optimizers/__init__.py +5 -0
  189. iaml/optimizers/bayesian_optimizer.py +193 -0
  190. iaml/optimizers/genetic_optimizer.py +284 -0
  191. iaml/optimizers/optimizer.py +31 -0
  192. iaml/optimizers/random_optimizer.py +101 -0
  193. iaml/plot.py +138 -0
  194. iaml/plots/__init__.py +32 -0
  195. iaml/plots/bar_plot.py +141 -0
  196. iaml/plots/box_plot.py +166 -0
  197. iaml/plots/class_prediction_error_plot.py +37 -0
  198. iaml/plots/classification_report_plot.py +35 -0
  199. iaml/plots/confusion_matrix_plot.py +34 -0
  200. iaml/plots/correlation_heatmap_plot.py +201 -0
  201. iaml/plots/cumulative_hazard_plot.py +72 -0
  202. iaml/plots/density_plot.py +210 -0
  203. iaml/plots/histogram_plot.py +179 -0
  204. iaml/plots/kaplan_meier_comparison_plot.py +89 -0
  205. iaml/plots/line_plot.py +70 -0
  206. iaml/plots/missingness_heatmap_plot.py +203 -0
  207. iaml/plots/outlier_plot.py +217 -0
  208. iaml/plots/pair_plot.py +228 -0
  209. iaml/plots/precision_recall_curve_plot.py +86 -0
  210. iaml/plots/prediction_error_plot.py +34 -0
  211. iaml/plots/qq_plot.py +220 -0
  212. iaml/plots/residual_plot.py +38 -0
  213. iaml/plots/roc_dynamique_curve_plot.py +79 -0
  214. iaml/plots/rocauc_plot.py +96 -0
  215. iaml/plots/shap_plot.py +187 -0
  216. iaml/plots/target_distribution_plot.py +241 -0
  217. iaml/plots/violin_plot.py +206 -0
  218. iaml/predictor.py +139 -0
  219. iaml/reference.py +65 -0
  220. iaml/shared_cache.py +90 -0
  221. iaml/sklearn_preprocessor.py +74 -0
  222. iaml/splitters/__init__.py +3 -0
  223. iaml/splitters/kfold_splitter.py +32 -0
  224. iaml/splitters/random_splitter.py +26 -0
  225. iaml/stack.py +39 -0
  226. iaml/statistic.py +66 -0
  227. iaml/statistics/__init__.py +77 -0
  228. iaml/statistics/anova_statistic.py +80 -0
  229. iaml/statistics/cardinality_ratio_statistic.py +63 -0
  230. iaml/statistics/category_cooccurrence_statistic.py +79 -0
  231. iaml/statistics/chi_square_statistic.py +81 -0
  232. iaml/statistics/coef_variation_statistic.py +72 -0
  233. iaml/statistics/correlation_with_target.py +105 -0
  234. iaml/statistics/count.py +72 -0
  235. iaml/statistics/data_type_summary_statistic.py +74 -0
  236. iaml/statistics/duplicate_row_statistic.py +56 -0
  237. iaml/statistics/effect_size_statistic.py +129 -0
  238. iaml/statistics/entropy_statistic.py +69 -0
  239. iaml/statistics/event_rate_statistic.py +52 -0
  240. iaml/statistics/grouped_mean_statistic.py +60 -0
  241. iaml/statistics/iqr_statistic.py +66 -0
  242. iaml/statistics/kurtosis.py +50 -0
  243. iaml/statistics/mad_statistic.py +66 -0
  244. iaml/statistics/mean.py +61 -0
  245. iaml/statistics/median_statistic.py +61 -0
  246. iaml/statistics/minmax.py +60 -0
  247. iaml/statistics/missing_rate_statistic.py +62 -0
  248. iaml/statistics/mode.py +47 -0
  249. iaml/statistics/most_frequent_ratio.py +81 -0
  250. iaml/statistics/outlier_count_iqr_statistic.py +76 -0
  251. iaml/statistics/quantile.py +59 -0
  252. iaml/statistics/range.py +53 -0
  253. iaml/statistics/rare_category_rate.py +92 -0
  254. iaml/statistics/skewness.py +53 -0
  255. iaml/statistics/stdev.py +50 -0
  256. iaml/statistics/summary_table_statistic.py +60 -0
  257. iaml/statistics/time_by_group_statistic.py +83 -0
  258. iaml/statistics/time_summary_statistic.py +56 -0
  259. iaml/statistics/top_k_value_counts.py +68 -0
  260. iaml/statistics/unique_count_statistic.py +57 -0
  261. iaml/statistics/value_counts.py +63 -0
  262. iaml/statistics/variance.py +51 -0
  263. iaml/statistics/violin.py +63 -0
  264. iaml/step.py +600 -0
  265. iaml/step_cache.py +87 -0
  266. iaml/step_wrapper.py +79 -0
  267. iaml/timed_pool_executor.py +492 -0
  268. iaml/type_of_target.py +68 -0
  269. iaml/void_step.py +101 -0
  270. iaml/worker_manager.py +169 -0
  271. iaml/wrapper/__init__.py +4 -0
  272. iaml/wrapper/wrap_basic_gridsearch.py +68 -0
  273. iaml/wrapper/wrap_genetic_gridsearch.py +293 -0
  274. iaml/wrapper/wrap_iterative_gridsearch.py +399 -0
  275. pyiaml-1.0.0.dist-info/METADATA +802 -0
  276. pyiaml-1.0.0.dist-info/RECORD +279 -0
  277. pyiaml-1.0.0.dist-info/WHEEL +5 -0
  278. pyiaml-1.0.0.dist-info/licenses/LICENSE +674 -0
  279. pyiaml-1.0.0.dist-info/top_level.txt +1 -0
iaml/statistic.py ADDED
@@ -0,0 +1,66 @@
1
+ """[STATISTIC] Parent of descriptive statistics."""
2
+ from __future__ import annotations
3
+
4
+ from typing import Any
5
+ import pandas as pd
6
+
7
+ from .dataset import Dataset
8
+ from .reference import Reference
9
+
10
+
11
+ class Statistic:
12
+ """[STATISTIC] Parent of descriptive statistics."""
13
+
14
+ name: str = ""
15
+ """Name of the statistic."""
16
+
17
+ _description: str = ""
18
+ """Short description of the statistic."""
19
+
20
+ _description_long: str = ""
21
+ """Long description of the statistic."""
22
+
23
+ refs: list[dict[str, Any]] = []
24
+ """List of references for this statistic."""
25
+
26
+ @classmethod
27
+ def all_subclasses(cls) -> list['Statistic']:
28
+ """Return all statistic subclasses."""
29
+ subclasses = cls.__subclasses__()
30
+ for subclass in subclasses:
31
+ subclasses += subclass.all_subclasses()
32
+ return subclasses
33
+
34
+ @classmethod
35
+ def get_refs(cls) -> list[Reference]:
36
+ """Get bibliography references."""
37
+ if hasattr(cls, 'refs'):
38
+ return [Reference(ref, cls.__name__) for ref in cls.refs]
39
+ return []
40
+
41
+ @property
42
+ def description(self) -> str:
43
+ """Return the short description."""
44
+ return self._description.replace('\n', '')
45
+
46
+ @property
47
+ def description_long(self) -> str:
48
+ """Return the long description."""
49
+ return self._description_long.replace('\n', '')
50
+
51
+ def explain(self) -> str:
52
+ """Describe statistic."""
53
+ return self.description_long
54
+
55
+ def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
56
+ """Compute the statistic on the dataset."""
57
+ raise NotImplementedError('Subclass must implement abstract method')
58
+
59
+ def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
60
+ """Return True if the statistic applies to the dataset."""
61
+ return False
62
+
63
+ @property
64
+ def name(self) -> str:
65
+ """Return the statistic formatted name."""
66
+ return ' '.join(x.title() for x in str(self).split('_'))
@@ -0,0 +1,77 @@
1
+ """All statistics to describe original dataset."""
2
+ from .count import CountStatistic
3
+ from .mean import MeanStatistic
4
+ from .minmax import BoundStatistic
5
+ from .mode import ModeStatistic
6
+ from .quantile import QuantileStatistic
7
+ from .range import RangeStatistic
8
+ from .stdev import StdevStatistic
9
+ from .value_counts import ValueCountsStatistic
10
+ from .variance import VarianceStatistic
11
+ from .violin import ViolinStatistic
12
+
13
+ from .summary_table_statistic import SummaryTableStatistic
14
+ from .data_type_summary_statistic import DataTypeSummaryStatistic
15
+ from .duplicate_row_statistic import DuplicateRowStatistic
16
+ from .unique_count_statistic import UniqueCountStatistic
17
+ from .missing_rate_statistic import MissingRateStatistic
18
+ from .cardinality_ratio_statistic import CardinalityRatioStatistic
19
+ from .median_statistic import MedianStatistic
20
+ from .iqr_statistic import IQRStatistic
21
+ from .mad_statistic import MADStatistic
22
+ from .coef_variation_statistic import CoefVariationStatistic
23
+ from .outlier_count_iqr_statistic import OutlierCountIQRStatistic
24
+ from .skewness import SkewnessStatistic
25
+ from .kurtosis import KurtosisStatistic
26
+ from .top_k_value_counts import TopKValueCountsStatistic
27
+ from .entropy_statistic import EntropyStatistic
28
+ from .rare_category_rate import RareCategoryRateStatistic
29
+ from .most_frequent_ratio import MostFrequentRatioStatistic
30
+ from .category_cooccurrence_statistic import CategoryCooccurrenceStatistic
31
+ from .grouped_mean_statistic import GroupedMeanStatistic
32
+ from .effect_size_statistic import EffectSizeStatistic
33
+ from .anova_statistic import ANOVAStatistic
34
+ from .chi_square_statistic import ChiSquareStatistic
35
+ from .correlation_with_target import CorrelationWithTargetStatistic
36
+ from .event_rate_statistic import EventRateStatistic
37
+ from .time_summary_statistic import TimeSummaryStatistic
38
+ from .time_by_group_statistic import TimeByGroupStatistic
39
+
40
+ __all__ = [
41
+ "CountStatistic",
42
+ "MeanStatistic",
43
+ "BoundStatistic",
44
+ "ModeStatistic",
45
+ "QuantileStatistic",
46
+ "RangeStatistic",
47
+ "StdevStatistic",
48
+ "ValueCountsStatistic",
49
+ "VarianceStatistic",
50
+ "ViolinStatistic",
51
+ "SummaryTableStatistic",
52
+ "DataTypeSummaryStatistic",
53
+ "DuplicateRowStatistic",
54
+ "UniqueCountStatistic",
55
+ "MissingRateStatistic",
56
+ "CardinalityRatioStatistic",
57
+ "MedianStatistic",
58
+ "IQRStatistic",
59
+ "MADStatistic",
60
+ "CoefVariationStatistic",
61
+ "OutlierCountIQRStatistic",
62
+ "SkewnessStatistic",
63
+ "KurtosisStatistic",
64
+ "TopKValueCountsStatistic",
65
+ "EntropyStatistic",
66
+ "RareCategoryRateStatistic",
67
+ "MostFrequentRatioStatistic",
68
+ "CategoryCooccurrenceStatistic",
69
+ "GroupedMeanStatistic",
70
+ "EffectSizeStatistic",
71
+ "ANOVAStatistic",
72
+ "ChiSquareStatistic",
73
+ "CorrelationWithTargetStatistic",
74
+ "EventRateStatistic",
75
+ "TimeSummaryStatistic",
76
+ "TimeByGroupStatistic",
77
+ ]
@@ -0,0 +1,80 @@
1
+ """[STATISTIC] ANOVA."""
2
+ from __future__ import annotations
3
+
4
+ import textwrap
5
+ import pandas as pd
6
+ from scipy import stats
7
+
8
+ from ..dataset import Dataset
9
+ from ..data_type import DataType
10
+ from ..statistic import Statistic
11
+
12
+
13
+ class ANOVAStatistic(Statistic):
14
+ """[STATISTIC] ANOVA."""
15
+
16
+ name: str = "ANOVA"
17
+ _description: str = textwrap.dedent("""\
18
+ ANOVA tests whether numerical feature means differ across classes.
19
+ """)
20
+ _description_long: str = textwrap.dedent("""\
21
+ ANOVA computes one-way p-values for numerical columns across classes.
22
+ Per-class columns report ANOVA p-values comparing each class against the
23
+ rest of the data, while the `_all` suffix reports the overall ANOVA p-value.
24
+ """)
25
+ refs: list[dict] = []
26
+
27
+ def __str__(self) -> str:
28
+ return 'anova'
29
+
30
+ def _anova_pvalue(self, groups: list[pd.Series]) -> float | None:
31
+ cleaned = []
32
+ for values in groups:
33
+ if values is None:
34
+ continue
35
+ series = values.dropna()
36
+ if series.size > 1:
37
+ cleaned.append(series.to_numpy())
38
+ if len(cleaned) < 2:
39
+ return None
40
+ result = stats.f_oneway(*cleaned)
41
+ pvalue = float(result.pvalue)
42
+ if pd.isna(pvalue):
43
+ return None
44
+ return pvalue
45
+
46
+ def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
47
+ """Compute ANOVA p-values for numerical columns."""
48
+ if dataset.type_of_target in ['survival', 'continuous']:
49
+ return pd.DataFrame()
50
+
51
+ numeric_columns = dataset.get_columns_names_by_type(DataType.NUMERIC)
52
+ if not numeric_columns:
53
+ return pd.DataFrame()
54
+
55
+ class_labels = list(pd.unique(dataset.y))
56
+ class_masks = {label: (dataset.y == label) for label in class_labels}
57
+
58
+ data = []
59
+ columns = []
60
+
61
+ for col in numeric_columns:
62
+ col_values = dataset.X[col]
63
+ overall_groups = [col_values[mask] for mask in class_masks.values()]
64
+ overall_pvalue = self._anova_pvalue(overall_groups)
65
+
66
+ for label in ['all'] + class_labels:
67
+ columns.append(f"{col}_{label}")
68
+ if label == 'all':
69
+ data.append(overall_pvalue)
70
+ else:
71
+ mask = class_masks[label]
72
+ class_values = col_values[mask]
73
+ rest_values = col_values[~mask]
74
+ data.append(self._anova_pvalue([class_values, rest_values]))
75
+
76
+ return pd.DataFrame([data], index=[str(self)], columns=columns)
77
+
78
+ def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
79
+ """Does this statistic apply to the dataset?"""
80
+ return dataset.type_of_target not in ['survival', 'continuous']
@@ -0,0 +1,63 @@
1
+ """[STATISTIC] Cardinality 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 CardinalityRatioStatistic(Statistic):
13
+ """[STATISTIC] Cardinality Ratio."""
14
+
15
+ name: str = "Cardinality Ratio"
16
+ _description: str = textwrap.dedent("""\
17
+ Cardinality ratio measures the ratio of unique values to total rows.
18
+ """)
19
+ _description_long: str = textwrap.dedent("""\
20
+ Cardinality ratio measures the ratio of unique values to total rows,
21
+ optionally per class for classification.
22
+ """)
23
+ refs: list[dict] = []
24
+
25
+ def __str__(self) -> str:
26
+ return 'cardinality_ratio'
27
+
28
+ def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
29
+ """Compute cardinality ratios 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
+ n_rows = int(dataset.X.shape[0])
38
+ for col in dataset.X.columns:
39
+ if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
40
+ columns.append(col)
41
+ n_unique = dataset.X[col].nunique(dropna=True)
42
+ ratio = n_unique / n_rows if n_rows else 0.0
43
+ data.append(ratio)
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
+ n_unique = values.nunique(dropna=True)
57
+ ratio = n_unique / n_rows if n_rows else 0.0
58
+ data.append(ratio)
59
+ return pd.DataFrame([data], index=[str(self)], columns=columns)
60
+
61
+ def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
62
+ """Does this statistic apply to the dataset?"""
63
+ return dataset.type_of_target != 'survival'
@@ -0,0 +1,79 @@
1
+ """[STATISTIC] Category Cooccurrence."""
2
+ from __future__ import annotations
3
+
4
+ import itertools
5
+ import textwrap
6
+ import pandas as pd
7
+
8
+ from ..dataset import Dataset
9
+ from ..data_type import DataType
10
+ from ..statistic import Statistic
11
+
12
+
13
+ class CategoryCooccurrenceStatistic(Statistic):
14
+ """[STATISTIC] Category Cooccurrence."""
15
+
16
+ name: str = "Category Cooccurrence"
17
+ _description: str = textwrap.dedent("""\
18
+ Category cooccurrence counts value pairs between categorical column pairs.
19
+ """)
20
+ _description_long: str = textwrap.dedent("""\
21
+ Category cooccurrence counts value pairs between categorical column pairs,
22
+ optionally per class for classification.
23
+ """)
24
+ refs: list[dict] = []
25
+
26
+ def __str__(self) -> str:
27
+ return 'category_cooccurrence'
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 _cooccurrence(self, frame: pd.DataFrame, col_a: str, col_b: str) -> list[tuple[tuple, int]]:
41
+ values = frame[[col_a, col_b]].dropna()
42
+ if values.empty:
43
+ return []
44
+ counts = values.groupby([col_a, col_b], sort=True).size()
45
+ return [((idx_a, idx_b), int(count)) for (idx_a, idx_b), count in counts.items()]
46
+
47
+ def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
48
+ """Compute category cooccurrence for categorical column pairs."""
49
+ if dataset.type_of_target == 'survival':
50
+ return pd.DataFrame()
51
+
52
+ columns = self._select_columns(dataset)
53
+ if len(columns) < 2:
54
+ return pd.DataFrame()
55
+
56
+ pairs = list(itertools.combinations(columns, 2))
57
+ data = []
58
+ df_columns = []
59
+
60
+ if dataset.type_of_target == 'continuous':
61
+ for col_a, col_b in pairs:
62
+ df_columns.append(f"{col_a}__{col_b}")
63
+ data.append(self._cooccurrence(dataset.X, col_a, col_b))
64
+ return pd.DataFrame([data], index=[str(self)], columns=df_columns)
65
+
66
+ class_labels = list(pd.unique(dataset.y))
67
+ for col_a, col_b in pairs:
68
+ for label in ['all'] + class_labels:
69
+ df_columns.append(f"{col_a}__{col_b}_{label}")
70
+ if label == 'all':
71
+ frame = dataset.X
72
+ else:
73
+ frame = dataset.X.loc[dataset.y == label]
74
+ data.append(self._cooccurrence(frame, col_a, col_b))
75
+ return pd.DataFrame([data], index=[str(self)], columns=df_columns)
76
+
77
+ def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
78
+ """Does this statistic apply to the dataset?"""
79
+ return dataset.type_of_target != 'survival'
@@ -0,0 +1,81 @@
1
+ """[STATISTIC] Chi-square."""
2
+ from __future__ import annotations
3
+
4
+ import textwrap
5
+ import pandas as pd
6
+ from scipy.stats import chi2_contingency
7
+
8
+ from ..dataset import Dataset
9
+ from ..data_type import DataType
10
+ from ..statistic import Statistic
11
+
12
+
13
+ class ChiSquareStatistic(Statistic):
14
+ """[STATISTIC] Chi-square."""
15
+
16
+ name: str = "Chi-square"
17
+ _description: str = textwrap.dedent("""\
18
+ Chi-square measures association between categorical columns and classes.
19
+ """)
20
+ _description_long: str = textwrap.dedent("""\
21
+ Chi-square computes the chi-square test statistic for each categorical column
22
+ against the target classes. The `_all` suffix reports the multi-class statistic,
23
+ while per-class values compare a class against the rest.
24
+ """)
25
+ refs: list[dict] = []
26
+
27
+ def __str__(self) -> str:
28
+ return 'chi_square'
29
+
30
+ def _select_columns(self, dataset: Dataset) -> list[str]:
31
+ columns = dataset.get_columns_names_by_type(DataType.CATEGORICAL)
32
+ category_columns = list(dataset.X.select_dtypes(include=['category']).columns)
33
+ seen = set()
34
+ ordered = []
35
+ for column in columns + category_columns:
36
+ if column in dataset.X.columns and column not in seen:
37
+ ordered.append(column)
38
+ seen.add(column)
39
+ return ordered
40
+
41
+ def _chi2_statistic(self, feature: pd.Series, target: pd.Series) -> float | None:
42
+ if not isinstance(target, pd.Series):
43
+ target = pd.Series(target, index=feature.index)
44
+ mask = feature.notna() & target.notna()
45
+ if not mask.any():
46
+ return None
47
+ table = pd.crosstab(feature[mask], target[mask])
48
+ if table.empty or table.shape[0] < 2 or table.shape[1] < 2:
49
+ return None
50
+ stat, _, _, _ = chi2_contingency(table, correction=False)
51
+ if pd.isna(stat):
52
+ return None
53
+ return float(stat)
54
+
55
+ def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
56
+ """Compute chi-square statistics for categorical columns."""
57
+ if dataset.type_of_target in ['survival', 'continuous']:
58
+ return pd.DataFrame()
59
+
60
+ columns = self._select_columns(dataset)
61
+ if not columns:
62
+ return pd.DataFrame()
63
+
64
+ class_labels = list(pd.unique(dataset.y))
65
+ data = []
66
+ df_columns = []
67
+
68
+ for col in columns:
69
+ for label in ['all'] + class_labels:
70
+ df_columns.append(f"{col}_{label}")
71
+ if label == 'all':
72
+ data.append(self._chi2_statistic(dataset.X[col], dataset.y))
73
+ else:
74
+ binary_target = pd.Series(dataset.y == label, index=dataset.X.index)
75
+ data.append(self._chi2_statistic(dataset.X[col], binary_target))
76
+
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 not in ['survival', 'continuous']
@@ -0,0 +1,72 @@
1
+ """[STATISTIC] Coefficient of variation."""
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 CoefVariationStatistic(Statistic):
13
+ """[STATISTIC] Coefficient of variation."""
14
+
15
+ name: str = "Coef Variation"
16
+ _description: str = textwrap.dedent("""\
17
+ Coefficient of variation measures relative dispersion (std/mean).
18
+ """)
19
+ _description_long: str = textwrap.dedent("""\
20
+ Coefficient of variation measures relative dispersion (std/mean),
21
+ optionally per class for classification.
22
+ """)
23
+ refs: list[dict] = []
24
+
25
+ def __str__(self) -> str:
26
+ return 'coef_variation'
27
+
28
+ def _coef_variation(self, values: pd.Series) -> float | None:
29
+ mean = values.mean()
30
+ if pd.isna(mean) or mean == 0:
31
+ return None
32
+ stdev = values.std()
33
+ if pd.isna(stdev):
34
+ return None
35
+ return stdev / mean
36
+
37
+ def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
38
+ """Compute coefficient of variation for numerical columns."""
39
+ if dataset.type_of_target == 'survival':
40
+ return pd.DataFrame()
41
+
42
+ data = []
43
+ columns = []
44
+
45
+ if dataset.type_of_target == 'continuous':
46
+ for col in dataset.X.columns:
47
+ if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
48
+ columns.append(col)
49
+ if dataset.columns_types[col][1] == DataType.NUMERIC:
50
+ data.append(self._coef_variation(dataset.X[col]))
51
+ else:
52
+ data.append(None)
53
+ return pd.DataFrame([data], index=[str(self)], columns=columns)
54
+
55
+ class_labels = list(pd.unique(dataset.y))
56
+ for col in dataset.X.columns:
57
+ if dataset.columns_types[col][1] not in (DataType.TEXT, DataType.SHORT_TEXT):
58
+ for label in ['all'] + class_labels:
59
+ columns.append(f"{col}_{label}")
60
+ if dataset.columns_types[col][1] == DataType.NUMERIC:
61
+ if label == 'all':
62
+ values = dataset.X[col]
63
+ else:
64
+ values = dataset.X.loc[dataset.y == label][col]
65
+ data.append(self._coef_variation(values))
66
+ else:
67
+ data.append(None)
68
+ return pd.DataFrame([data], index=[str(self)], columns=columns)
69
+
70
+ def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
71
+ """Does this statistic apply to the dataset?"""
72
+ return dataset.type_of_target != 'survival'
@@ -0,0 +1,105 @@
1
+ """[STATISTIC] Correlation with target."""
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 CorrelationWithTargetStatistic(Statistic):
13
+ """[STATISTIC] Correlation with target."""
14
+
15
+ name: str = "Correlation with target"
16
+ _description: str = textwrap.dedent("""\
17
+ Correlation (continuous targets) or eta (classification) for numeric columns.
18
+ """)
19
+ _description_long: str = textwrap.dedent("""\
20
+ For continuous targets, this reports Pearson correlations between each numeric
21
+ feature and the target. For classification targets, this reports the eta
22
+ correlation ratio between each numeric feature and the target classes. The
23
+ `_all` suffix reports the multi-class statistic, while per-class values compare
24
+ a class against the rest.
25
+ """)
26
+ refs: list[dict] = []
27
+
28
+ def __str__(self) -> str:
29
+ return 'correlation_with_target'
30
+
31
+ def _pearson_corr(self, feature: pd.Series, target: pd.Series) -> float | None:
32
+ if not isinstance(target, pd.Series):
33
+ target = pd.Series(target, index=feature.index)
34
+ values = pd.to_numeric(feature, errors='coerce')
35
+ target_values = pd.to_numeric(target, errors='coerce')
36
+ mask = values.notna() & target_values.notna()
37
+ if mask.sum() < 2:
38
+ return None
39
+ if values[mask].nunique() < 2 or target_values[mask].nunique() < 2:
40
+ return None
41
+ corr = values[mask].corr(target_values[mask])
42
+ if pd.isna(corr):
43
+ return None
44
+ return float(corr)
45
+
46
+ def _eta(self, feature: pd.Series, target: pd.Series) -> float | None:
47
+ if not isinstance(target, pd.Series):
48
+ target = pd.Series(target, index=feature.index)
49
+ mask = feature.notna() & target.notna()
50
+ if not mask.any():
51
+ return None
52
+ values = feature[mask]
53
+ groups = target[mask]
54
+ if groups.nunique() < 2:
55
+ return None
56
+ overall_mean = values.mean()
57
+ ss_total = ((values - overall_mean) ** 2).sum()
58
+ if ss_total == 0:
59
+ return None
60
+ ss_between = 0.0
61
+ for _, group_values in values.groupby(groups):
62
+ count = group_values.size
63
+ if count == 0:
64
+ continue
65
+ mean = group_values.mean()
66
+ ss_between += count * (mean - overall_mean) ** 2
67
+ eta_sq = ss_between / ss_total
68
+ if pd.isna(eta_sq):
69
+ return None
70
+ return float(eta_sq) ** 0.5
71
+
72
+ def compute(self, dataset: Dataset, **kwargs) -> pd.DataFrame:
73
+ """Compute correlations or eta with the target for numeric columns."""
74
+ if dataset.type_of_target == 'survival':
75
+ return pd.DataFrame()
76
+
77
+ numeric_columns = dataset.get_columns_names_by_type(DataType.NUMERIC)
78
+ if not numeric_columns:
79
+ return pd.DataFrame()
80
+
81
+ data = []
82
+ columns = []
83
+
84
+ if dataset.type_of_target == 'continuous':
85
+ for col in numeric_columns:
86
+ columns.append(col)
87
+ data.append(self._pearson_corr(dataset.X[col], dataset.y))
88
+ return pd.DataFrame([data], index=[str(self)], columns=columns)
89
+
90
+ class_labels = list(pd.unique(dataset.y))
91
+ for col in numeric_columns:
92
+ overall_eta = self._eta(dataset.X[col], dataset.y)
93
+ for label in ['all'] + class_labels:
94
+ columns.append(f"{col}_{label}")
95
+ if label == 'all':
96
+ data.append(overall_eta)
97
+ else:
98
+ binary_target = pd.Series(dataset.y == label, index=dataset.X.index)
99
+ data.append(self._eta(dataset.X[col], binary_target))
100
+
101
+ return pd.DataFrame([data], index=[str(self)], columns=columns)
102
+
103
+ def suitable(self, dataset: Dataset) -> bool: # pylint: disable=unused-argument
104
+ """Does this statistic apply to the dataset?"""
105
+ return dataset.type_of_target != 'survival'