upgini 1.2.156.dev3__tar.gz → 1.2.156.dev4__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 (83) hide show
  1. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/PKG-INFO +1 -1
  2. upgini-1.2.156.dev4/src/upgini/__about__.py +1 -0
  3. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/date.py +172 -45
  4. upgini-1.2.156.dev3/src/upgini/__about__.py +0 -1
  5. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/.gitignore +0 -0
  6. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/LICENSE +0 -0
  7. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/README.md +0 -0
  8. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/pyproject.toml +0 -0
  9. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/__init__.py +0 -0
  10. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/ads.py +0 -0
  11. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/ads_management/__init__.py +0 -0
  12. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/ads_management/ads_manager.py +0 -0
  13. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/__init__.py +0 -0
  14. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/all_operators.py +0 -0
  15. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/binary.py +0 -0
  16. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/feature.py +0 -0
  17. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/groupby.py +0 -0
  18. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/operator.py +0 -0
  19. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/__init__.py +0 -0
  20. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/base.py +0 -0
  21. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/cross.py +0 -0
  22. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/delta.py +0 -0
  23. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/lag.py +0 -0
  24. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/roll.py +0 -0
  25. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/trend.py +0 -0
  26. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/timeseries/volatility.py +0 -0
  27. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/unary.py +0 -0
  28. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/utils.py +0 -0
  29. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/autofe/vector.py +0 -0
  30. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/data_source/__init__.py +0 -0
  31. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/data_source/data_source_publisher.py +0 -0
  32. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/dataset.py +0 -0
  33. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/errors.py +0 -0
  34. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/features_enricher.py +0 -0
  35. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/http.py +0 -0
  36. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/mdc/__init__.py +0 -0
  37. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/mdc/context.py +0 -0
  38. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/metadata.py +0 -0
  39. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/metrics.py +0 -0
  40. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/normalizer/__init__.py +0 -0
  41. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/normalizer/normalize_utils.py +0 -0
  42. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/resource_bundle/__init__.py +0 -0
  43. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/resource_bundle/exceptions.py +0 -0
  44. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/resource_bundle/strings.properties +0 -0
  45. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/resource_bundle/strings_widget.properties +0 -0
  46. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/sampler/__init__.py +0 -0
  47. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/sampler/base.py +0 -0
  48. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/sampler/random_under_sampler.py +0 -0
  49. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/sampler/utils.py +0 -0
  50. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/search_task.py +0 -0
  51. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/spinner.py +0 -0
  52. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/Roboto-Regular.ttf +0 -0
  53. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/__init__.py +0 -0
  54. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/base_search_key_detector.py +0 -0
  55. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/blocked_time_series.py +0 -0
  56. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/config.py +0 -0
  57. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/country_utils.py +0 -0
  58. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/custom_loss_utils.py +0 -0
  59. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/cv_utils.py +0 -0
  60. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/datetime_utils.py +0 -0
  61. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/deduplicate_utils.py +0 -0
  62. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/display_utils.py +0 -0
  63. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/email_utils.py +0 -0
  64. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/fallback_progress_bar.py +0 -0
  65. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/feature_info.py +0 -0
  66. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/features_validator.py +0 -0
  67. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/format.py +0 -0
  68. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/hash_utils.py +0 -0
  69. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/ip_utils.py +0 -0
  70. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/mstats.py +0 -0
  71. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/one_hot_encoder.py +0 -0
  72. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/phone_utils.py +0 -0
  73. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/postal_code_utils.py +0 -0
  74. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/progress_bar.py +0 -0
  75. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/psi.py +0 -0
  76. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/sample_utils.py +0 -0
  77. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/sklearn_ext.py +0 -0
  78. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/sort.py +0 -0
  79. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/target_utils.py +0 -0
  80. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/track_info.py +0 -0
  81. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/ts_utils.py +0 -0
  82. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/utils/warning_counter.py +0 -0
  83. {upgini-1.2.156.dev3 → upgini-1.2.156.dev4}/src/upgini/version_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: upgini
3
- Version: 1.2.156.dev3
3
+ Version: 1.2.156.dev4
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.2.156.dev4"
@@ -113,18 +113,30 @@ _ext_aggregations = {"nunique": (lambda x: len(np.unique(x)), 0), "count": (len,
113
113
  _count_aggregations = ["nunique", "count"]
114
114
 
115
115
 
116
- class DateListDiff(PandasOperator, DateDiffMixin, ParametrizedOperator):
116
+ def _aggregate_diffs(values: np.ndarray, aggregation: str) -> float:
117
+ values = np.atleast_1d(np.asarray(values, dtype=np.float64))
118
+ method = getattr(np, aggregation, None)
119
+ default = np.nan
120
+ if method is None and aggregation in _ext_aggregations:
121
+ method, default = _ext_aggregations[aggregation]
122
+ elif not callable(method):
123
+ raise ValueError(f"Unsupported aggregation: {aggregation}")
124
+
125
+ return method(values) if len(values) > 0 else default
126
+
127
+
128
+ class DateListDiffLists(PandasOperator, DateDiffMixin, ParametrizedOperator):
129
+ name: str = "date_diff_lists"
117
130
  is_binary: bool = True
118
131
  has_symmetry_importance: bool = True
132
+ output_type: Optional[str] = "vector"
119
133
 
120
- aggregation: str
121
134
  replace_negative: bool = False
122
135
 
123
136
  def get_params(self) -> Dict[str, Optional[str]]:
124
137
  res = super().get_params()
125
138
  res.update(
126
139
  {
127
- "aggregation": self.aggregation,
128
140
  "diff_unit": self.diff_unit,
129
141
  "left_unit": self.left_unit,
130
142
  "right_unit": self.right_unit,
@@ -134,16 +146,17 @@ class DateListDiff(PandasOperator, DateDiffMixin, ParametrizedOperator):
134
146
  return res
135
147
 
136
148
  def to_formula(self) -> str:
137
- return f"date_diff_{self.aggregation}"
149
+ return f"date_diff_lists_{self.diff_unit}"
138
150
 
139
151
  @classmethod
140
- def from_formula(cls, formula: str) -> Optional["DateListDiff"]:
141
- if not formula.startswith("date_diff_") or formula.startswith("date_diff_type"):
142
- return None
143
- aggregation = formula.replace("date_diff_", "")
144
- if "_" in aggregation:
145
- return None
146
- return cls(aggregation=aggregation)
152
+ def from_formula(cls, formula: str) -> Optional["DateListDiffLists"]:
153
+ if formula == "date_diff_lists":
154
+ return cls()
155
+ if formula.startswith("date_diff_lists_"):
156
+ diff_unit = formula.replace("date_diff_lists_", "")
157
+ if diff_unit in {"D", "Y"}:
158
+ return cls(diff_unit=diff_unit)
159
+ return None
147
160
 
148
161
  @staticmethod
149
162
  def _non_empty_list_mask(right: pd.Series) -> pd.Series:
@@ -168,48 +181,165 @@ class DateListDiff(PandasOperator, DateDiffMixin, ParametrizedOperator):
168
181
  }
169
182
  )
170
183
 
184
+ def _row_diffs(self, left_date, right_dates: pd.arrays.DatetimeArray) -> List[float]:
185
+ diffs = self._convert_diff_to_unit(left_date - right_dates)
186
+ if self.replace_negative:
187
+ diffs = diffs[diffs > 0]
188
+ return np.atleast_1d(np.asarray(diffs, dtype=np.float64)).tolist()
189
+
171
190
  def calculate_binary(self, left: pd.Series, right: pd.Series) -> pd.Series:
172
191
  if left.isna().all() or right.isna().all():
173
- return pd.Series([None] * len(left), index=left.index, dtype=np.float64)
192
+ return pd.Series([None] * len(left), index=left.index, dtype=object)
174
193
 
175
194
  left = self._convert_to_date(left, self.left_unit)
176
195
  right_mask = self._non_empty_list_mask(right)
177
196
  mask = left.notna() & right.notna() & right_mask
178
197
 
198
+ results = pd.Series([None] * len(left), index=left.index, dtype=object)
179
199
  if not mask.any():
180
- res = pd.Series(np.nan, index=left.index, dtype=np.float64)
181
- if self.aggregation in _count_aggregations:
182
- res[~right_mask] = 0.0
183
- return res
200
+ return results
184
201
 
185
202
  masked_left = left[mask]
186
203
  converted_lists = self._convert_date_lists(right[mask])
187
- results = np.empty(len(masked_left), dtype=np.float64)
204
+ for idx, left_date in masked_left.items():
205
+ results.loc[idx] = self._row_diffs(left_date, converted_lists[idx])
206
+ return results
207
+
208
+
209
+ class DateListDiffAggWithinBounds(PandasOperator, ParametrizedOperator):
210
+ name: str = "date_diff_list_agg"
211
+ is_unary: bool = True
212
+ output_type: Optional[str] = "float"
213
+
214
+ lower_bound: Optional[int] = None
215
+ upper_bound: Optional[int] = None
216
+ aggregation: str
217
+ normalize: Optional[bool] = None
218
+
219
+ def get_params(self) -> Dict[str, Optional[str]]:
220
+ res = super().get_params()
221
+ res.update(
222
+ {
223
+ "aggregation": self.aggregation,
224
+ "lower_bound": str(self.lower_bound) if self.lower_bound is not None else None,
225
+ "upper_bound": str(self.upper_bound) if self.upper_bound is not None else None,
226
+ "normalize": str(self.normalize) if self.normalize is not None else None,
227
+ }
228
+ )
229
+ return res
230
+
231
+ def to_formula(self) -> str:
232
+ lower_bound = "minusinf" if self.lower_bound is None else self.lower_bound
233
+ upper_bound = "plusinf" if self.upper_bound is None else self.upper_bound
234
+ norm = "_norm" if self.normalize else ""
235
+ return f"date_diff_list_agg_{lower_bound}_{upper_bound}_{self.aggregation}{norm}"
236
+
237
+ @classmethod
238
+ def from_formula(cls, formula: str) -> Optional["DateListDiffAggWithinBounds"]:
239
+ import re
240
+
241
+ normalize = formula.endswith("_norm")
242
+ formula = formula.replace("_norm", "")
243
+
244
+ pattern = r"^date_diff_list_agg_((minusinf|\d+))_((plusinf|\d+))_(\w+)$"
245
+ match = re.match(pattern, formula)
246
+ if not match:
247
+ return None
248
+
249
+ lower_bound = None if match.group(1) == "minusinf" else int(match.group(1))
250
+ upper_bound = None if match.group(3) == "plusinf" else int(match.group(3))
251
+ aggregation = match.group(5)
252
+ return cls(
253
+ lower_bound=lower_bound,
254
+ upper_bound=upper_bound,
255
+ aggregation=aggregation,
256
+ normalize=normalize,
257
+ )
258
+
259
+ def _aggregate_row(self, diffs) -> float:
260
+ if diffs is None or (isinstance(diffs, float) and np.isnan(diffs)):
261
+ return np.nan
262
+
263
+ diffs = np.atleast_1d(np.asarray(diffs, dtype=np.float64))
264
+ orig_len = len(diffs)
265
+ if self.lower_bound is not None or self.upper_bound is not None:
266
+ lower = self.lower_bound if self.lower_bound is not None else -np.inf
267
+ upper = self.upper_bound if self.upper_bound is not None else np.inf
268
+ diffs = diffs[(diffs >= lower) & (diffs < upper)]
269
+ agg_res = _aggregate_diffs(diffs, self.aggregation)
270
+ if self.normalize and orig_len > 0:
271
+ return agg_res / orig_len
272
+ return agg_res
273
+
274
+ def calculate_unary(self, data: pd.Series) -> pd.Series:
275
+ results = np.empty(len(data), dtype=np.float64)
188
276
  results[:] = np.nan
189
- for i, (idx, left_date) in enumerate(masked_left.items()):
190
- results[i] = self._agg(self._diff(left_date - converted_lists[idx]))
277
+ for i, diffs in enumerate(data.to_numpy()):
278
+ results[i] = self._aggregate_row(diffs)
279
+ return pd.Series(results, index=data.index, dtype=np.float64)
191
280
 
192
- res_masked = pd.Series(results, index=masked_left.index)
193
- res = res_masked.reindex(left.index.union(right.index))
194
- if self.aggregation in _count_aggregations:
195
- res[~right_mask] = 0.0
196
- res = res.astype(np.float64)
197
281
 
282
+ class DateListDiff(PandasOperator, DateDiffMixin, ParametrizedOperator):
283
+ is_binary: bool = True
284
+ has_symmetry_importance: bool = True
285
+
286
+ aggregation: str
287
+ replace_negative: bool = False
288
+
289
+ def get_params(self) -> Dict[str, Optional[str]]:
290
+ res = super().get_params()
291
+ res.update(
292
+ {
293
+ "aggregation": self.aggregation,
294
+ "diff_unit": self.diff_unit,
295
+ "left_unit": self.left_unit,
296
+ "right_unit": self.right_unit,
297
+ "replace_negative": self.replace_negative,
298
+ }
299
+ )
198
300
  return res
199
301
 
200
- def _diff(self, x: TimedeltaArray):
201
- x = self._convert_diff_to_unit(x)
202
- return x[x > 0] if self.replace_negative else x
302
+ def to_formula(self) -> str:
303
+ return f"date_diff_{self.aggregation}"
203
304
 
204
- def _agg(self, x):
205
- method = getattr(np, self.aggregation, None)
206
- default = np.nan
207
- if method is None and self.aggregation in _ext_aggregations:
208
- method, default = _ext_aggregations[self.aggregation]
209
- elif not callable(method):
210
- raise ValueError(f"Unsupported aggregation: {self.aggregation}")
305
+ @classmethod
306
+ def from_formula(cls, formula: str) -> Optional["DateListDiff"]:
307
+ if not formula.startswith("date_diff_") or formula.startswith("date_diff_type"):
308
+ return None
309
+ aggregation = formula.replace("date_diff_", "")
310
+ if "_" in aggregation:
311
+ return None
312
+ return cls(aggregation=aggregation)
211
313
 
212
- return method(x) if len(x) > 0 else default
314
+ def _lists_op(self) -> DateListDiffLists:
315
+ return DateListDiffLists(
316
+ diff_unit=self.diff_unit,
317
+ left_unit=self.left_unit,
318
+ right_unit=self.right_unit,
319
+ replace_negative=self.replace_negative,
320
+ )
321
+
322
+ def _agg_op(self) -> DateListDiffAggWithinBounds:
323
+ return DateListDiffAggWithinBounds(
324
+ lower_bound=None,
325
+ upper_bound=None,
326
+ aggregation=self.aggregation,
327
+ normalize=False,
328
+ )
329
+
330
+ def _compose_list_diff(self, left: pd.Series, right: pd.Series) -> pd.Series:
331
+ if left.isna().all() or right.isna().all():
332
+ return pd.Series([None] * len(left), index=left.index, dtype=np.float64)
333
+
334
+ right_mask = DateListDiffLists._non_empty_list_mask(right)
335
+ diff_lists = self._lists_op().calculate_binary(left, right)
336
+ result = self._agg_op().calculate_unary(diff_lists)
337
+ if self.aggregation in _count_aggregations:
338
+ result[~right_mask] = 0.0
339
+ return result.astype(np.float64)
340
+
341
+ def calculate_binary(self, left: pd.Series, right: pd.Series) -> pd.Series:
342
+ return self._compose_list_diff(left, right)
213
343
 
214
344
 
215
345
  class DateListDiffBounded(DateListDiff, ParametrizedOperator):
@@ -258,16 +388,13 @@ class DateListDiffBounded(DateListDiff, ParametrizedOperator):
258
388
  res["normalize"] = str(self.normalize)
259
389
  return res
260
390
 
261
- def _agg(self, x):
262
- orig_len = len(x)
263
- x = x[
264
- (x >= (self.lower_bound if self.lower_bound is not None else -np.inf))
265
- & (x < (self.upper_bound if self.upper_bound is not None else np.inf))
266
- ]
267
- agg_res = super()._agg(x)
268
- if self.normalize and orig_len > 0:
269
- return agg_res / orig_len
270
- return agg_res
391
+ def _agg_op(self) -> DateListDiffAggWithinBounds:
392
+ return DateListDiffAggWithinBounds(
393
+ lower_bound=self.lower_bound,
394
+ upper_bound=self.upper_bound,
395
+ aggregation=self.aggregation,
396
+ normalize=self.normalize or False,
397
+ )
271
398
 
272
399
 
273
400
  class DatePercentileBase(PandasOperator, abc.ABC):
@@ -1 +0,0 @@
1
- __version__ = "1.2.156.dev3"
File without changes
File without changes
File without changes