upgini 1.1.285__tar.gz → 1.1.286__tar.gz

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 (64) hide show
  1. {upgini-1.1.285 → upgini-1.1.286}/PKG-INFO +1 -1
  2. upgini-1.1.286/src/upgini/__about__.py +1 -0
  3. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/all_operands.py +2 -1
  4. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/date.py +85 -2
  5. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/feature.py +22 -5
  6. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/operand.py +4 -2
  7. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/features_enricher.py +13 -10
  8. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/metadata.py +3 -1
  9. upgini-1.1.285/src/upgini/__about__.py +0 -1
  10. {upgini-1.1.285 → upgini-1.1.286}/.gitignore +0 -0
  11. {upgini-1.1.285 → upgini-1.1.286}/LICENSE +0 -0
  12. {upgini-1.1.285 → upgini-1.1.286}/README.md +0 -0
  13. {upgini-1.1.285 → upgini-1.1.286}/pyproject.toml +0 -0
  14. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/__init__.py +0 -0
  15. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/ads.py +0 -0
  16. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/ads_management/__init__.py +0 -0
  17. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/ads_management/ads_manager.py +0 -0
  18. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/__init__.py +0 -0
  19. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/binary.py +0 -0
  20. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/groupby.py +0 -0
  21. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/unary.py +0 -0
  22. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/autofe/vector.py +0 -0
  23. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/data_source/__init__.py +0 -0
  24. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/data_source/data_source_publisher.py +0 -0
  25. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/dataset.py +0 -0
  26. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/errors.py +0 -0
  27. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/http.py +0 -0
  28. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/mdc/__init__.py +0 -0
  29. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/mdc/context.py +0 -0
  30. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/metrics.py +0 -0
  31. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/normalizer/__init__.py +0 -0
  32. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/normalizer/phone_normalizer.py +0 -0
  33. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/resource_bundle/__init__.py +0 -0
  34. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/resource_bundle/exceptions.py +0 -0
  35. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/resource_bundle/strings.properties +0 -0
  36. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/resource_bundle/strings_widget.properties +0 -0
  37. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/sampler/__init__.py +0 -0
  38. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/sampler/base.py +0 -0
  39. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/sampler/random_under_sampler.py +0 -0
  40. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/sampler/utils.py +0 -0
  41. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/search_task.py +0 -0
  42. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/spinner.py +0 -0
  43. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/__init__.py +0 -0
  44. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/base_search_key_detector.py +0 -0
  45. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/blocked_time_series.py +0 -0
  46. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/country_utils.py +0 -0
  47. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/custom_loss_utils.py +0 -0
  48. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/cv_utils.py +0 -0
  49. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/datetime_utils.py +0 -0
  50. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/deduplicate_utils.py +0 -0
  51. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/display_utils.py +0 -0
  52. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/email_utils.py +0 -0
  53. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/fallback_progress_bar.py +0 -0
  54. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/features_validator.py +0 -0
  55. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/format.py +0 -0
  56. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/ip_utils.py +0 -0
  57. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/phone_utils.py +0 -0
  58. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/postal_code_utils.py +0 -0
  59. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/progress_bar.py +0 -0
  60. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/sklearn_ext.py +0 -0
  61. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/target_utils.py +0 -0
  62. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/track_info.py +0 -0
  63. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/utils/warning_counter.py +0 -0
  64. {upgini-1.1.285 → upgini-1.1.286}/src/upgini/version_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: upgini
3
- Version: 1.1.285
3
+ Version: 1.1.286
4
4
  Summary: Intelligent data search & enrichment for Machine Learning
5
5
  Project-URL: Bug Reports, https://github.com/upgini/upgini/issues
6
6
  Project-URL: Homepage, https://upgini.com/
@@ -0,0 +1 @@
1
+ __version__ = "1.1.286"
@@ -1,7 +1,7 @@
1
1
  from typing import Dict
2
2
 
3
3
  from upgini.autofe.binary import Add, Divide, Max, Min, Multiply, Sim, Subtract
4
- from upgini.autofe.date import DateDiff, DateDiffType2, DateListDiff, DateListDiffBounded
4
+ from upgini.autofe.date import DateDiff, DateDiffType2, DateListDiff, DateListDiffBounded, DatePercentile
5
5
  from upgini.autofe.groupby import GroupByThenAgg, GroupByThenRank
6
6
  from upgini.autofe.operand import Operand
7
7
  from upgini.autofe.unary import Abs, Floor, Freq, Log, Residual, Sigmoid, Sqrt, Square
@@ -49,6 +49,7 @@ ALL_OPERANDS: Dict[str, Operand] = {
49
49
  DateListDiffBounded(diff_unit="Y", aggregation="count", lower_bound=30, upper_bound=45),
50
50
  DateListDiffBounded(diff_unit="Y", aggregation="count", lower_bound=45, upper_bound=60),
51
51
  DateListDiffBounded(diff_unit="Y", aggregation="count", lower_bound=60),
52
+ DatePercentile(),
52
53
  ]
53
54
  }
54
55
 
@@ -1,9 +1,9 @@
1
- from typing import Any, Optional, Union
1
+ from typing import Any, Dict, List, Optional, Union
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
5
5
  from pandas.core.arrays.timedeltas import TimedeltaArray
6
- from pydantic import BaseModel
6
+ from pydantic import BaseModel, validator
7
7
 
8
8
  from upgini.autofe.operand import PandasOperand
9
9
 
@@ -27,6 +27,17 @@ class DateDiff(PandasOperand, DateDiffMixin):
27
27
  is_binary = True
28
28
  has_symmetry_importance = True
29
29
 
30
+ def get_params(self) -> Dict[str, Optional[str]]:
31
+ res = super().get_params()
32
+ res.update(
33
+ {
34
+ "diff_unit": self.diff_unit,
35
+ "left_unit": self.left_unit,
36
+ "right_unit": self.right_unit,
37
+ }
38
+ )
39
+ return res
40
+
30
41
  def calculate_binary(self, left: pd.Series, right: pd.Series) -> pd.Series:
31
42
  left = self._convert_to_date(left, self.left_unit)
32
43
  right = self._convert_to_date(right, self.right_unit)
@@ -42,6 +53,17 @@ class DateDiffType2(PandasOperand, DateDiffMixin):
42
53
  is_binary = True
43
54
  has_symmetry_importance = True
44
55
 
56
+ def get_params(self) -> Dict[str, Optional[str]]:
57
+ res = super().get_params()
58
+ res.update(
59
+ {
60
+ "diff_unit": self.diff_unit,
61
+ "left_unit": self.left_unit,
62
+ "right_unit": self.right_unit,
63
+ }
64
+ )
65
+ return res
66
+
45
67
  def calculate_binary(self, left: pd.Series, right: pd.Series) -> pd.Series:
46
68
  left = self._convert_to_date(left, self.left_unit)
47
69
  right = self._convert_to_date(right, self.right_unit)
@@ -64,6 +86,15 @@ class DateListDiff(PandasOperand, DateDiffMixin):
64
86
  has_symmetry_importance = True
65
87
  aggregation: str
66
88
 
89
+ def get_params(self) -> Dict[str, Optional[str]]:
90
+ res = super().get_params()
91
+ res.update(
92
+ {
93
+ "aggregation": self.aggregation,
94
+ }
95
+ )
96
+ return res
97
+
67
98
  def __init__(self, **data: Any) -> None:
68
99
  if "name" not in data:
69
100
  data["name"] = f"date_diff_{data.get('aggregation')}"
@@ -116,3 +147,55 @@ class DateListDiffBounded(DateListDiff):
116
147
  def _agg(self, x):
117
148
  x = x[(x >= (self.lower_bound or -np.inf)) & (x < (self.upper_bound or np.inf))]
118
149
  return super()._agg(x)
150
+
151
+
152
+ class DatePercentile(PandasOperand):
153
+ name = "date_per"
154
+ is_binary = True
155
+ output_type = "float"
156
+
157
+ date_unit: Optional[str] = None
158
+ zero_month: Optional[int]
159
+ zero_year: Optional[int]
160
+ zero_bounds: Optional[List[float]]
161
+ step: int = 30
162
+
163
+ def get_params(self) -> Dict[str, Optional[str]]:
164
+ res = super().get_params()
165
+ res.update(
166
+ {
167
+ "date_unit": self.date_unit,
168
+ "zero_month": self.zero_month,
169
+ "zero_year": self.zero_year,
170
+ "zero_bounds": self.zero_bounds,
171
+ "step": self.step,
172
+ }
173
+ )
174
+ return res
175
+
176
+ @validator("zero_bounds", pre=True)
177
+ def validate_bounds(cls, value):
178
+ if value is None or isinstance(value, list):
179
+ return value
180
+ elif isinstance(value, str):
181
+ return value[1:-1].split(", ")
182
+
183
+ def calculate_binary(self, left: pd.Series, right: pd.Series) -> pd.Series:
184
+ # Assuming that left is a date column, right is a feature column
185
+ left = pd.to_datetime(left, unit=self.date_unit)
186
+ months = left.dt.month
187
+ years = left.dt.year
188
+
189
+ month_diffs = 12 * (years - (self.zero_year or 0)) + (months - (self.zero_month or 0))
190
+ bounds = month_diffs.apply(
191
+ lambda d: np.array(self.zero_bounds if self.zero_bounds is not None else []) + d * self.step
192
+ )
193
+
194
+ return right.index.to_series().apply(lambda i: self.__perc(right[i], bounds[i]))
195
+
196
+ def __perc(self, f, bounds):
197
+ hit = np.where(f >= bounds)[0]
198
+ if hit.size > 0:
199
+ return np.max(hit) + 1
200
+ else:
201
+ return np.nan
@@ -1,6 +1,6 @@
1
1
  import hashlib
2
2
  import itertools
3
- from typing import Dict, List, Optional, Tuple, Union
3
+ from typing import Dict, List, Optional, Set, Tuple, Union
4
4
 
5
5
  import numpy as np
6
6
  import pandas as pd
@@ -16,6 +16,12 @@ class Column:
16
16
  self.data = data
17
17
  self.calculate_all = calculate_all
18
18
 
19
+ def get_display_name(self, cache: bool = True, shorten: bool = False, **kwargs) -> str:
20
+ return self.name
21
+
22
+ def set_op_params(self, params: Dict[str, str]) -> "Column":
23
+ return self
24
+
19
25
  def rename_columns(self, mapping: Dict[str, str]) -> "Column":
20
26
  self.name = self._unhash(mapping.get(self.name) or self.name)
21
27
  return self
@@ -69,19 +75,30 @@ class Feature:
69
75
  self.cached_display_name = cached_display_name
70
76
  self.alias = alias
71
77
 
72
- def set_op_params(self, params: Dict[str, str]) -> "Feature":
78
+ def set_op_params(self, params: Optional[Dict[str, str]]) -> "Feature":
79
+ obj_dict = self.op.dict().copy()
80
+ obj_dict.update(params or {})
81
+ self.op = self.op.__class__.parse_obj(obj_dict)
73
82
  self.op.set_params(params)
83
+
84
+ for child in self.children:
85
+ child.set_op_params(params)
74
86
  return self
75
87
 
76
88
  def get_hash(self) -> str:
77
- return hashlib.sha256("_".join([self.op.name] + [ch.name for ch in self.children]).encode("utf-8")).hexdigest()[
78
- :8
79
- ]
89
+ return hashlib.sha256(
90
+ "_".join([self.op.name] + [ch.get_display_name() for ch in self.children]).encode("utf-8")
91
+ ).hexdigest()[:8]
80
92
 
81
93
  def set_alias(self, alias: str) -> "Feature":
82
94
  self.alias = alias
83
95
  return self
84
96
 
97
+ def get_all_operand_names(self) -> Set[str]:
98
+ return {self.op.name}.union(
99
+ {n for f in self.children if isinstance(f, Feature) for n in f.get_all_operand_names()}
100
+ )
101
+
85
102
  def rename_columns(self, mapping: Dict[str, str]) -> "Feature":
86
103
  for child in self.children:
87
104
  child.rename_columns(mapping)
@@ -25,8 +25,10 @@ class Operand(BaseModel):
25
25
  self.params = params
26
26
  return self
27
27
 
28
- def get_params(self) -> Dict[str, str]:
29
- return self.params
28
+ def get_params(self) -> Dict[str, Optional[str]]:
29
+ res = {"alias": self.alias}
30
+ res.update(self.params or {})
31
+ return res
30
32
 
31
33
 
32
34
  MAIN_COLUMN = "main_column"
@@ -1451,15 +1451,12 @@ class FeaturesEnricher(TransformerMixin):
1451
1451
  if len(decimal_columns_to_fix) > 0:
1452
1452
  for col in decimal_columns_to_fix:
1453
1453
  fitting_eval_X[col] = (
1454
- fitting_eval_X[col]
1455
- .astype("string").str
1456
- .replace(",", ".", regex=False)
1457
- .astype(np.float64)
1454
+ fitting_eval_X[col].astype("string").str.replace(",", ".", regex=False).astype(np.float64)
1458
1455
  )
1459
1456
  fitting_enriched_eval_X[col] = (
1460
1457
  fitting_enriched_eval_X[col]
1461
- .astype("string").str
1462
- .replace(",", ".", regex=False)
1458
+ .astype("string")
1459
+ .str.replace(",", ".", regex=False)
1463
1460
  .astype(np.float64)
1464
1461
  )
1465
1462
 
@@ -3278,10 +3275,16 @@ class FeaturesEnricher(TransformerMixin):
3278
3275
 
3279
3276
  descriptions = []
3280
3277
  for m in autofe_meta:
3281
- autofe_feature = Feature.from_formula(m.formula)
3282
3278
  orig_to_hashed = {base_column.original_name: base_column.hashed_name for base_column in m.base_columns}
3283
- autofe_feature.rename_columns(orig_to_hashed)
3284
- autofe_feature.set_display_index(m.display_index)
3279
+
3280
+ autofe_feature = (
3281
+ Feature.from_formula(m.formula)
3282
+ .set_display_index(m.display_index)
3283
+ .set_alias(m.alias)
3284
+ .set_op_params(m.operator_params or {})
3285
+ .rename_columns(orig_to_hashed)
3286
+ )
3287
+
3285
3288
  if autofe_feature.op.is_vector:
3286
3289
  continue
3287
3290
 
@@ -3302,7 +3305,7 @@ class FeaturesEnricher(TransformerMixin):
3302
3305
  description[f"Feature {feature_idx}"] = bc.hashed_name
3303
3306
  feature_idx += 1
3304
3307
 
3305
- description["Function"] = autofe_feature.op.name
3308
+ description["Function"] = ",".join(sorted(autofe_feature.get_all_operand_names()))
3306
3309
 
3307
3310
  descriptions.append(description)
3308
3311
 
@@ -256,9 +256,11 @@ class BaseColumnMetadata(BaseModel):
256
256
 
257
257
 
258
258
  class GeneratedFeatureMetadata(BaseModel):
259
- formula: str # on hashed names
259
+ alias: Optional[str]
260
+ formula: str
260
261
  display_index: str
261
262
  base_columns: List[BaseColumnMetadata]
263
+ operator_params: Optional[Dict[str, str]]
262
264
 
263
265
 
264
266
  class ProviderTaskMetadataV2(BaseModel):
@@ -1 +0,0 @@
1
- __version__ = "1.1.285"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes