upgini 1.2.157.dev1__tar.gz → 1.2.157.dev3__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.
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/PKG-INFO +1 -1
- upgini-1.2.157.dev3/src/upgini/__about__.py +1 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/binary.py +18 -3
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/date.py +1 -1
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/feature.py +14 -18
- upgini-1.2.157.dev3/src/upgini/autofe/operand.py +133 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/operator.py +17 -14
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/cross.py +1 -1
- upgini-1.2.157.dev1/src/upgini/__about__.py +0 -1
- upgini-1.2.157.dev1/src/upgini/autofe/operand.py +0 -73
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/.gitignore +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/LICENSE +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/README.md +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/pyproject.toml +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/ads.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/ads_management/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/ads_management/ads_manager.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/all_operators.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/groupby.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/base.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/delta.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/lag.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/roll.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/trend.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/timeseries/volatility.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/unary.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/autofe/vector.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/data_source/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/data_source/data_source_publisher.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/dataset.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/errors.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/features_enricher.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/http.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/mdc/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/mdc/context.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/metadata.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/metrics.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/normalizer/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/normalizer/normalize_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/resource_bundle/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/resource_bundle/exceptions.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/resource_bundle/strings.properties +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/resource_bundle/strings_widget.properties +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/sampler/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/sampler/base.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/sampler/random_under_sampler.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/sampler/utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/search_task.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/spinner.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/Roboto-Regular.ttf +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/__init__.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/base_search_key_detector.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/blocked_time_series.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/config.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/country_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/custom_loss_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/cv_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/datetime_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/deduplicate_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/display_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/email_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/fallback_progress_bar.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/feature_info.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/features_validator.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/format.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/hash_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/ip_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/mstats.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/one_hot_encoder.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/phone_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/postal_code_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/progress_bar.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/psi.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/sample_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/sklearn_ext.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/sort.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/target_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/track_info.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/ts_utils.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/utils/warning_counter.py +0 -0
- {upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/version_validator.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.2.157.dev3"
|
|
@@ -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
|
|
162
|
-
|
|
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,
|
|
11
|
+
from upgini.autofe.operand import CalculationContext, OperandValue, operand_to_output
|
|
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
|
|
@@ -62,9 +62,14 @@ class Column:
|
|
|
62
62
|
def infer_type(self, data: pd.DataFrame) -> DtypeObj:
|
|
63
63
|
return data[self.name].dtype
|
|
64
64
|
|
|
65
|
-
def calculate(
|
|
65
|
+
def calculate(
|
|
66
|
+
self,
|
|
67
|
+
data: Union[pd.DataFrame, CalculationContext],
|
|
68
|
+
preserve_kind: bool = False,
|
|
69
|
+
) -> Union[pd.Series, OperandValue]:
|
|
66
70
|
ctx = data if isinstance(data, CalculationContext) else CalculationContext.from_dataframe(data)
|
|
67
|
-
|
|
71
|
+
operand = self._eval(ctx)
|
|
72
|
+
return operand if preserve_kind else operand.as_series()
|
|
68
73
|
|
|
69
74
|
def _eval(self, ctx: CalculationContext) -> OperandValue:
|
|
70
75
|
self.data = ctx.resolve_operand(self.name)
|
|
@@ -245,10 +250,11 @@ class Feature:
|
|
|
245
250
|
self,
|
|
246
251
|
data: Union[pd.DataFrame, CalculationContext],
|
|
247
252
|
is_root: bool = False,
|
|
248
|
-
|
|
253
|
+
preserve_kind: bool = False,
|
|
254
|
+
) -> Union[pd.Series, pd.DataFrame, OperandValue]:
|
|
249
255
|
ctx = data if isinstance(data, CalculationContext) else CalculationContext.from_dataframe(data)
|
|
250
256
|
result = self._eval(ctx)
|
|
251
|
-
new_data =
|
|
257
|
+
new_data = operand_to_output(result, preserve_kind=preserve_kind)
|
|
252
258
|
|
|
253
259
|
if is_root:
|
|
254
260
|
self.data = new_data
|
|
@@ -258,24 +264,14 @@ class Feature:
|
|
|
258
264
|
if isinstance(self.op, PandasOperator):
|
|
259
265
|
if self.op.is_vector:
|
|
260
266
|
operands = [child._eval(ctx) for child in self.children]
|
|
261
|
-
|
|
262
|
-
return wrap_operand(result)
|
|
267
|
+
return self.op.calculate(data=operands)
|
|
263
268
|
left = self.children[0]._eval(ctx)
|
|
264
269
|
if len(self.children) < 2:
|
|
265
|
-
|
|
266
|
-
return wrap_operand(result, source=left.source)
|
|
270
|
+
return self.op.calculate(data=left)
|
|
267
271
|
right = self.children[1]._eval(ctx)
|
|
268
|
-
|
|
269
|
-
return wrap_operand(result, source=left.source)
|
|
272
|
+
return self.op.calculate(left=left, right=right)
|
|
270
273
|
raise NotImplementedError(f"Unrecognized operator {self.op.name}.")
|
|
271
274
|
|
|
272
|
-
@staticmethod
|
|
273
|
-
def _operand_to_output(operand: OperandValue) -> Union[pd.Series, pd.DataFrame]:
|
|
274
|
-
new_data = operand.as_series()
|
|
275
|
-
if (str(new_data.dtype) == "category") | (str(new_data.dtype) == "object"):
|
|
276
|
-
return new_data
|
|
277
|
-
return new_data.replace([-np.inf, np.inf], np.nan)
|
|
278
|
-
|
|
279
275
|
@staticmethod
|
|
280
276
|
def check_xor(left: Union[Column, "Feature"], right: Union[Column, "Feature"]) -> bool:
|
|
281
277
|
def _get_all_columns(feature: Union[Column, "Feature"]) -> List[str]:
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Dict, Optional, Union
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OperandKind(str, Enum):
|
|
12
|
+
SERIES = "series"
|
|
13
|
+
MATRIX = "matrix"
|
|
14
|
+
ARRAY = "array"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class OperandValue:
|
|
19
|
+
kind: OperandKind
|
|
20
|
+
data: Union[pd.Series, np.ndarray]
|
|
21
|
+
index: pd.Index
|
|
22
|
+
source: Optional[str] = None
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_series(cls, series: pd.Series, source: Optional[str] = None) -> "OperandValue":
|
|
26
|
+
return cls(kind=OperandKind.SERIES, data=series, index=series.index, source=source)
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def from_matrix(cls, matrix: np.ndarray, index: pd.Index, source: Optional[str] = None) -> "OperandValue":
|
|
30
|
+
return cls(kind=OperandKind.MATRIX, data=matrix, index=index, source=source)
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def from_array(cls, array: np.ndarray, index: pd.Index, source: Optional[str] = None) -> "OperandValue":
|
|
34
|
+
return cls(kind=OperandKind.ARRAY, data=array, index=index, source=source)
|
|
35
|
+
|
|
36
|
+
def as_series(self) -> pd.Series:
|
|
37
|
+
if self.kind == OperandKind.SERIES:
|
|
38
|
+
return self.data # type: ignore[return-value]
|
|
39
|
+
if self.kind == OperandKind.ARRAY:
|
|
40
|
+
return pd.Series(self.data, index=self.index, dtype=np.float64)
|
|
41
|
+
if self.kind == OperandKind.MATRIX:
|
|
42
|
+
return pd.Series(list(self.as_matrix()), index=self.index)
|
|
43
|
+
raise TypeError(f"Cannot convert operand kind {self.kind.value} to series")
|
|
44
|
+
|
|
45
|
+
def as_matrix(self) -> np.ndarray:
|
|
46
|
+
if self.kind != OperandKind.MATRIX:
|
|
47
|
+
raise TypeError(f"Cannot convert operand kind {self.kind.value} to matrix")
|
|
48
|
+
return self.data # type: ignore[return-value]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class CalculationContext:
|
|
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}")
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def index(self) -> pd.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")
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_dataframe(cls, data: pd.DataFrame) -> "CalculationContext":
|
|
78
|
+
return cls(data=data)
|
|
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
|
+
|
|
88
|
+
def resolve_operand(self, name: str) -> OperandValue:
|
|
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)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def finalize_operand(operand: OperandValue) -> OperandValue:
|
|
98
|
+
if operand.kind == OperandKind.MATRIX:
|
|
99
|
+
matrix = np.where(np.isinf(operand.as_matrix()), np.nan, operand.as_matrix())
|
|
100
|
+
return OperandValue.from_matrix(matrix, index=operand.index, source=operand.source)
|
|
101
|
+
if operand.kind == OperandKind.ARRAY:
|
|
102
|
+
array = operand.data # type: ignore[assignment]
|
|
103
|
+
array = np.where(np.isinf(array), np.nan, array)
|
|
104
|
+
return OperandValue.from_array(array, index=operand.index, source=operand.source)
|
|
105
|
+
new_data = operand.as_series()
|
|
106
|
+
if (str(new_data.dtype) == "category") | (str(new_data.dtype) == "object"):
|
|
107
|
+
return OperandValue.from_series(new_data, source=operand.source)
|
|
108
|
+
return OperandValue.from_series(new_data.replace([-np.inf, np.inf], np.nan), source=operand.source)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def operand_to_output(operand: OperandValue, preserve_kind: bool = False) -> Union[pd.Series, OperandValue]:
|
|
112
|
+
finalized = finalize_operand(operand)
|
|
113
|
+
if preserve_kind:
|
|
114
|
+
return finalized
|
|
115
|
+
return finalized.as_series()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def wrap_operand(
|
|
119
|
+
result: Union[pd.Series, np.ndarray, "OperandValue"],
|
|
120
|
+
source: Optional[str] = None,
|
|
121
|
+
index: Optional[pd.Index] = None,
|
|
122
|
+
) -> "OperandValue":
|
|
123
|
+
if isinstance(result, OperandValue):
|
|
124
|
+
return result
|
|
125
|
+
if isinstance(result, np.ndarray):
|
|
126
|
+
if index is None:
|
|
127
|
+
raise TypeError("index is required when wrapping ndarray result")
|
|
128
|
+
if result.ndim == 1:
|
|
129
|
+
return OperandValue.from_array(result, index=index, source=source)
|
|
130
|
+
if result.ndim == 2:
|
|
131
|
+
return OperandValue.from_matrix(result, index=index, source=source)
|
|
132
|
+
raise TypeError(f"Cannot wrap ndarray with {result.ndim} dimensions")
|
|
133
|
+
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) ->
|
|
143
|
+
def calculate(self, **kwargs) -> OperandValue:
|
|
144
144
|
if self.is_unary:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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(
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.2.157.dev1"
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from enum import Enum
|
|
5
|
-
from typing import Optional, Union
|
|
6
|
-
|
|
7
|
-
import numpy as np
|
|
8
|
-
import pandas as pd
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class OperandKind(str, Enum):
|
|
12
|
-
SERIES = "series"
|
|
13
|
-
MATRIX = "matrix"
|
|
14
|
-
ARRAY = "array"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@dataclass
|
|
18
|
-
class OperandValue:
|
|
19
|
-
kind: OperandKind
|
|
20
|
-
data: Union[pd.Series, np.ndarray]
|
|
21
|
-
index: pd.Index
|
|
22
|
-
source: Optional[str] = None
|
|
23
|
-
|
|
24
|
-
@classmethod
|
|
25
|
-
def from_series(cls, series: pd.Series, source: Optional[str] = None) -> "OperandValue":
|
|
26
|
-
return cls(kind=OperandKind.SERIES, data=series, index=series.index, source=source)
|
|
27
|
-
|
|
28
|
-
@classmethod
|
|
29
|
-
def from_matrix(cls, matrix: np.ndarray, index: pd.Index, source: Optional[str] = None) -> "OperandValue":
|
|
30
|
-
return cls(kind=OperandKind.MATRIX, data=matrix, index=index, source=source)
|
|
31
|
-
|
|
32
|
-
@classmethod
|
|
33
|
-
def from_array(cls, array: np.ndarray, index: pd.Index, source: Optional[str] = None) -> "OperandValue":
|
|
34
|
-
return cls(kind=OperandKind.ARRAY, data=array, index=index, source=source)
|
|
35
|
-
|
|
36
|
-
def as_series(self) -> pd.Series:
|
|
37
|
-
if self.kind == OperandKind.SERIES:
|
|
38
|
-
return self.data # type: ignore[return-value]
|
|
39
|
-
if self.kind == OperandKind.ARRAY:
|
|
40
|
-
return pd.Series(self.data, index=self.index, dtype=np.float64)
|
|
41
|
-
if self.kind == OperandKind.MATRIX:
|
|
42
|
-
return pd.Series(list(self.as_matrix()), index=self.index)
|
|
43
|
-
raise TypeError(f"Cannot convert operand kind {self.kind.value} to series")
|
|
44
|
-
|
|
45
|
-
def as_matrix(self) -> np.ndarray:
|
|
46
|
-
if self.kind != OperandKind.MATRIX:
|
|
47
|
-
raise TypeError(f"Cannot convert operand kind {self.kind.value} to matrix")
|
|
48
|
-
return self.data # type: ignore[return-value]
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@dataclass
|
|
52
|
-
class CalculationContext:
|
|
53
|
-
data: pd.DataFrame
|
|
54
|
-
|
|
55
|
-
@property
|
|
56
|
-
def index(self) -> pd.Index:
|
|
57
|
-
return self.data.index
|
|
58
|
-
|
|
59
|
-
@classmethod
|
|
60
|
-
def from_dataframe(cls, data: pd.DataFrame) -> "CalculationContext":
|
|
61
|
-
return cls(data=data)
|
|
62
|
-
|
|
63
|
-
def resolve_operand(self, name: str) -> OperandValue:
|
|
64
|
-
return OperandValue.from_series(self.data[name], source=name)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def wrap_operand(
|
|
68
|
-
result: Union[pd.Series, "OperandValue"],
|
|
69
|
-
source: Optional[str] = None,
|
|
70
|
-
) -> "OperandValue":
|
|
71
|
-
if isinstance(result, OperandValue):
|
|
72
|
-
return result
|
|
73
|
-
return OperandValue.from_series(result, source=source)
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{upgini-1.2.157.dev1 → upgini-1.2.157.dev3}/src/upgini/resource_bundle/strings_widget.properties
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|