upgini 1.2.157.dev1__tar.gz → 1.2.157.dev2__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 (84) hide show
  1. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/PKG-INFO +1 -1
  2. upgini-1.2.157.dev2/src/upgini/__about__.py +1 -0
  3. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/binary.py +18 -3
  4. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/date.py +1 -1
  5. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/feature.py +4 -7
  6. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/operand.py +45 -6
  7. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/operator.py +17 -14
  8. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/cross.py +1 -1
  9. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/unary.py +1 -1
  10. upgini-1.2.157.dev1/src/upgini/__about__.py +0 -1
  11. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/.gitignore +0 -0
  12. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/LICENSE +0 -0
  13. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/README.md +0 -0
  14. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/pyproject.toml +0 -0
  15. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/__init__.py +0 -0
  16. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/ads.py +0 -0
  17. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/ads_management/__init__.py +0 -0
  18. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/ads_management/ads_manager.py +0 -0
  19. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/__init__.py +0 -0
  20. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/all_operators.py +0 -0
  21. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/groupby.py +0 -0
  22. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/__init__.py +0 -0
  23. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/base.py +0 -0
  24. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/delta.py +0 -0
  25. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/lag.py +0 -0
  26. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/roll.py +0 -0
  27. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/trend.py +0 -0
  28. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/timeseries/volatility.py +0 -0
  29. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/utils.py +0 -0
  30. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/autofe/vector.py +0 -0
  31. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/data_source/__init__.py +0 -0
  32. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/data_source/data_source_publisher.py +0 -0
  33. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/dataset.py +0 -0
  34. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/errors.py +0 -0
  35. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/features_enricher.py +0 -0
  36. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/http.py +0 -0
  37. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/mdc/__init__.py +0 -0
  38. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/mdc/context.py +0 -0
  39. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/metadata.py +0 -0
  40. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/metrics.py +0 -0
  41. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/normalizer/__init__.py +0 -0
  42. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/normalizer/normalize_utils.py +0 -0
  43. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/resource_bundle/__init__.py +0 -0
  44. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/resource_bundle/exceptions.py +0 -0
  45. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/resource_bundle/strings.properties +0 -0
  46. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/resource_bundle/strings_widget.properties +0 -0
  47. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/sampler/__init__.py +0 -0
  48. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/sampler/base.py +0 -0
  49. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/sampler/random_under_sampler.py +0 -0
  50. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/sampler/utils.py +0 -0
  51. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/search_task.py +0 -0
  52. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/spinner.py +0 -0
  53. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/Roboto-Regular.ttf +0 -0
  54. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/__init__.py +0 -0
  55. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/base_search_key_detector.py +0 -0
  56. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/blocked_time_series.py +0 -0
  57. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/config.py +0 -0
  58. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/country_utils.py +0 -0
  59. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/custom_loss_utils.py +0 -0
  60. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/cv_utils.py +0 -0
  61. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/datetime_utils.py +0 -0
  62. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/deduplicate_utils.py +0 -0
  63. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/display_utils.py +0 -0
  64. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/email_utils.py +0 -0
  65. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/fallback_progress_bar.py +0 -0
  66. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/feature_info.py +0 -0
  67. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/features_validator.py +0 -0
  68. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/format.py +0 -0
  69. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/hash_utils.py +0 -0
  70. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/ip_utils.py +0 -0
  71. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/mstats.py +0 -0
  72. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/one_hot_encoder.py +0 -0
  73. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/phone_utils.py +0 -0
  74. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/postal_code_utils.py +0 -0
  75. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/progress_bar.py +0 -0
  76. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/psi.py +0 -0
  77. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/sample_utils.py +0 -0
  78. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/sklearn_ext.py +0 -0
  79. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/sort.py +0 -0
  80. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/target_utils.py +0 -0
  81. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/track_info.py +0 -0
  82. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/ts_utils.py +0 -0
  83. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/src/upgini/utils/warning_counter.py +0 -0
  84. {upgini-1.2.157.dev1 → upgini-1.2.157.dev2}/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.157.dev1
3
+ Version: 1.2.157.dev2
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.157.dev2"
@@ -6,7 +6,7 @@ import numpy as np
6
6
  import pandas as pd
7
7
  from jarowinkler import jarowinkler_similarity
8
8
 
9
- from upgini.autofe.operand import OperandValue
9
+ from upgini.autofe.operand import OperandKind, OperandValue
10
10
  from upgini.autofe.operator import PandasOperator, VectorizableMixin
11
11
 
12
12
 
@@ -158,8 +158,23 @@ class Distance(PandasOperator):
158
158
  has_symmetry_importance: bool = True
159
159
 
160
160
  def calculate_binary(self, left: OperandValue, right: OperandValue) -> pd.Series:
161
- left = left.as_series()
162
- right = right.as_series()
161
+ if left.kind == OperandKind.MATRIX and right.kind == OperandKind.MATRIX:
162
+ return self._calculate_binary_matrices(left, right)
163
+ return self._calculate_binary_series(left.as_series(), right.as_series())
164
+
165
+ def _calculate_binary_matrices(self, left: OperandValue, right: OperandValue) -> pd.Series:
166
+ left_mat = left.as_matrix()
167
+ right_mat = right.as_matrix()
168
+ dot = np.sum(left_mat * right_mat, axis=1)
169
+ left_norm = np.sqrt(np.sum(left_mat * left_mat, axis=1))
170
+ right_norm = np.sqrt(np.sum(right_mat * right_mat, axis=1))
171
+ denom = left_norm * right_norm
172
+ with np.errstate(invalid="ignore", divide="ignore"):
173
+ result = 1 - dot / denom
174
+ result[denom == 0] = np.nan
175
+ return pd.Series(result, index=left.index, dtype=np.float64)
176
+
177
+ def _calculate_binary_series(self, left: pd.Series, right: pd.Series) -> pd.Series:
163
178
  return pd.Series(
164
179
  1 - self.__dot(left, right) / (self.__norm(left) * self.__norm(right)), index=left.index
165
180
  ).astype(np.float64)
@@ -341,7 +341,7 @@ class DateListDiff(PandasOperator, DateDiffMixin, ParametrizedOperator):
341
341
 
342
342
  right_mask = DateListDiffLists._non_empty_list_mask(right)
343
343
  diff_lists = self._lists_op().calculate(left=left, right=right)
344
- result = self._agg_op().calculate(data=diff_lists)
344
+ result = self._agg_op().calculate(data=diff_lists).as_series()
345
345
  if self.aggregation in _count_aggregations:
346
346
  result[~right_mask] = 0.0
347
347
  return result.astype(np.float64)
@@ -8,7 +8,7 @@ import pandas as pd
8
8
  from pandas._typing import DtypeObj
9
9
 
10
10
  from upgini.autofe.all_operators import find_op
11
- from upgini.autofe.operand import CalculationContext, OperandValue, wrap_operand
11
+ from upgini.autofe.operand import CalculationContext, OperandValue
12
12
  from upgini.autofe.operator import Operator, PandasOperator
13
13
  from upgini.autofe.timeseries.base import TimeSeriesBase
14
14
  from upgini.autofe.utils import pydantic_dump_method, pydantic_parse_method
@@ -258,15 +258,12 @@ class Feature:
258
258
  if isinstance(self.op, PandasOperator):
259
259
  if self.op.is_vector:
260
260
  operands = [child._eval(ctx) for child in self.children]
261
- result = self.op.calculate(data=operands)
262
- return wrap_operand(result)
261
+ return self.op.calculate(data=operands)
263
262
  left = self.children[0]._eval(ctx)
264
263
  if len(self.children) < 2:
265
- result = self.op.calculate(data=left)
266
- return wrap_operand(result, source=left.source)
264
+ return self.op.calculate(data=left)
267
265
  right = self.children[1]._eval(ctx)
268
- result = self.op.calculate(left=left, right=right)
269
- return wrap_operand(result, source=left.source)
266
+ return self.op.calculate(left=left, right=right)
270
267
  raise NotImplementedError(f"Unrecognized operator {self.op.name}.")
271
268
 
272
269
  @staticmethod
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dataclasses import dataclass
3
+ from dataclasses import dataclass, field
4
4
  from enum import Enum
5
- from typing import Optional, Union
5
+ from typing import Dict, Optional, Union
6
6
 
7
7
  import numpy as np
8
8
  import pandas as pd
@@ -50,24 +50,63 @@ class OperandValue:
50
50
 
51
51
  @dataclass
52
52
  class CalculationContext:
53
- data: pd.DataFrame
53
+ data: Optional[pd.DataFrame] = None
54
+ matrices: Dict[str, np.ndarray] = field(default_factory=dict)
55
+ row_index: Optional[pd.Index] = None
56
+
57
+ def __post_init__(self) -> None:
58
+ if self.data is None and not self.matrices:
59
+ raise ValueError("CalculationContext requires data and/or matrices")
60
+ if self.matrices:
61
+ lengths = {name: matrix.shape[0] for name, matrix in self.matrices.items()}
62
+ if len(set(lengths.values())) > 1:
63
+ raise ValueError(f"Matrix row counts mismatch: {lengths}")
54
64
 
55
65
  @property
56
66
  def index(self) -> pd.Index:
57
- return self.data.index
67
+ if self.data is not None:
68
+ return self.data.index
69
+ if self.row_index is not None:
70
+ return self.row_index
71
+ if self.matrices:
72
+ nrows = next(iter(self.matrices.values())).shape[0]
73
+ return pd.RangeIndex(nrows)
74
+ raise ValueError("CalculationContext has no index source")
58
75
 
59
76
  @classmethod
60
77
  def from_dataframe(cls, data: pd.DataFrame) -> "CalculationContext":
61
78
  return cls(data=data)
62
79
 
80
+ @classmethod
81
+ def from_matrices(
82
+ cls,
83
+ matrices: Dict[str, np.ndarray],
84
+ index: Optional[pd.Index] = None,
85
+ ) -> "CalculationContext":
86
+ return cls(matrices=matrices, row_index=index)
87
+
63
88
  def resolve_operand(self, name: str) -> OperandValue:
64
- return OperandValue.from_series(self.data[name], source=name)
89
+ matrix = self.matrices.get(name)
90
+ if matrix is not None:
91
+ return OperandValue.from_matrix(matrix, index=self.index, source=name)
92
+ if self.data is not None and name in self.data:
93
+ return OperandValue.from_series(self.data[name], source=name)
94
+ raise KeyError(name)
65
95
 
66
96
 
67
97
  def wrap_operand(
68
- result: Union[pd.Series, "OperandValue"],
98
+ result: Union[pd.Series, np.ndarray, "OperandValue"],
69
99
  source: Optional[str] = None,
100
+ index: Optional[pd.Index] = None,
70
101
  ) -> "OperandValue":
71
102
  if isinstance(result, OperandValue):
72
103
  return result
104
+ if isinstance(result, np.ndarray):
105
+ if index is None:
106
+ raise TypeError("index is required when wrapping ndarray result")
107
+ if result.ndim == 1:
108
+ return OperandValue.from_array(result, index=index, source=source)
109
+ if result.ndim == 2:
110
+ return OperandValue.from_matrix(result, index=index, source=source)
111
+ raise TypeError(f"Cannot wrap ndarray with {result.ndim} dimensions")
73
112
  return OperandValue.from_series(result, source=source)
@@ -6,7 +6,7 @@ import numpy as np
6
6
  import pandas as pd
7
7
  from pydantic import BaseModel, PrivateAttr
8
8
 
9
- from upgini.autofe.operand import OperandValue
9
+ from upgini.autofe.operand import OperandValue, wrap_operand
10
10
 
11
11
 
12
12
  class OperatorRegistry(type(BaseModel)):
@@ -140,26 +140,29 @@ class PandasOperator(Operator, abc.ABC):
140
140
  return value
141
141
  return OperandValue.from_series(value)
142
142
 
143
- def calculate(self, **kwargs) -> Union[pd.Series, OperandValue]:
143
+ def calculate(self, **kwargs) -> OperandValue:
144
144
  if self.is_unary:
145
- return self.calculate_unary(self._operand(kwargs["data"]))
146
- elif self.is_binary or self.is_grouping:
147
- return self.calculate_binary(
148
- self._operand(kwargs["left"]),
149
- self._operand(kwargs["right"]),
150
- )
151
- else:
152
- return self.calculate_vector([self._operand(value) for value in kwargs["data"]])
153
-
154
- def calculate_unary(self, data: OperandValue) -> Union[pd.Series, OperandValue]:
145
+ data = self._operand(kwargs["data"])
146
+ return wrap_operand(self.calculate_unary(data), source=data.source, index=data.index)
147
+ if self.is_binary or self.is_grouping:
148
+ left = self._operand(kwargs["left"])
149
+ right = self._operand(kwargs["right"])
150
+ return wrap_operand(self.calculate_binary(left, right), source=left.source, index=left.index)
151
+ operands = [self._operand(value) for value in kwargs["data"]]
152
+ index = operands[0].index if operands else None
153
+ return wrap_operand(self.calculate_vector(operands), index=index)
154
+
155
+ def calculate_unary(self, data: OperandValue) -> Union[pd.Series, np.ndarray, OperandValue]:
155
156
  pass
156
157
 
157
158
  def calculate_binary(
158
159
  self, left: OperandValue, right: OperandValue
159
- ) -> Union[pd.Series, OperandValue]:
160
+ ) -> Union[pd.Series, np.ndarray, OperandValue]:
160
161
  pass
161
162
 
162
- def calculate_vector(self, data: List[OperandValue]) -> Union[pd.Series, OperandValue]:
163
+ def calculate_vector(
164
+ self, data: List[OperandValue]
165
+ ) -> Union[pd.Series, np.ndarray, OperandValue]:
163
166
  pass
164
167
 
165
168
  def calculate_group(self, data: pd.DataFrame, **kwargs) -> pd.DataFrame:
@@ -126,7 +126,7 @@ class CrossSeriesInteraction(TimeSeriesBase, ParametrizedOperator):
126
126
  right_mask = self._get_mask(data, self.right_descriptor)
127
127
  right = self._extract_series(data, right_mask)
128
128
 
129
- interaction: pd.Series = self.interaction_op.calculate(left=left, right=right)
129
+ interaction: pd.Series = self.interaction_op.calculate(left=left, right=right).as_series()
130
130
  interaction = interaction.reindex(self._get_index(data))
131
131
  res = pd.Series(np.nan, index=data[-1].index, name=data[-1].name)
132
132
  res.loc[left_mask] = interaction[left_mask].values
@@ -162,7 +162,7 @@ class Embeddings(PandasOperator):
162
162
  name: str = "emb"
163
163
  is_unary: bool = True
164
164
  input_type: Optional[str] = "string"
165
- output_type: Optional[str] = "vector"
165
+ output_type: Optional[str] = "matrix"
166
166
 
167
167
 
168
168
  class Bin(PandasOperator):
@@ -1 +0,0 @@
1
- __version__ = "1.2.157.dev1"
File without changes
File without changes
File without changes