upgini 1.2.156.dev3__tar.gz → 1.2.156.dev5__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.156.dev3 → upgini-1.2.156.dev5}/PKG-INFO +1 -1
- upgini-1.2.156.dev5/src/upgini/__about__.py +1 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/binary.py +113 -16
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/date.py +172 -45
- upgini-1.2.156.dev3/src/upgini/__about__.py +0 -1
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/.gitignore +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/LICENSE +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/README.md +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/pyproject.toml +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/ads.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/ads_management/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/ads_management/ads_manager.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/all_operators.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/feature.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/groupby.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/operator.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/base.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/cross.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/delta.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/lag.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/roll.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/trend.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/timeseries/volatility.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/unary.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/autofe/vector.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/data_source/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/data_source/data_source_publisher.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/dataset.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/errors.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/features_enricher.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/http.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/mdc/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/mdc/context.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/metadata.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/metrics.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/normalizer/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/normalizer/normalize_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/resource_bundle/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/resource_bundle/exceptions.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/resource_bundle/strings.properties +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/resource_bundle/strings_widget.properties +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/sampler/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/sampler/base.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/sampler/random_under_sampler.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/sampler/utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/search_task.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/spinner.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/Roboto-Regular.ttf +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/__init__.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/base_search_key_detector.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/blocked_time_series.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/config.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/country_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/custom_loss_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/cv_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/datetime_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/deduplicate_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/display_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/email_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/fallback_progress_bar.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/feature_info.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/features_validator.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/format.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/hash_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/ip_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/mstats.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/one_hot_encoder.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/phone_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/postal_code_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/progress_bar.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/psi.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/sample_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/sklearn_ext.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/sort.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/target_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/track_info.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/ts_utils.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/utils/warning_counter.py +0 -0
- {upgini-1.2.156.dev3 → upgini-1.2.156.dev5}/src/upgini/version_validator.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.2.156.dev5"
|
|
@@ -140,23 +140,120 @@ class Distance(PandasOperator):
|
|
|
140
140
|
is_symmetrical: bool = True
|
|
141
141
|
has_symmetry_importance: bool = True
|
|
142
142
|
|
|
143
|
+
def _to_float_vector(self, value) -> Optional[np.ndarray]:
|
|
144
|
+
if value is None or (isinstance(value, float) and np.isnan(value)):
|
|
145
|
+
return None
|
|
146
|
+
return np.atleast_1d(np.asarray(value, dtype=np.float64))
|
|
147
|
+
|
|
148
|
+
def _stack_vectors(self, arr: np.ndarray, indices: np.ndarray) -> Optional[np.ndarray]:
|
|
149
|
+
try:
|
|
150
|
+
stacked = np.vstack(arr[indices])
|
|
151
|
+
except (ValueError, TypeError):
|
|
152
|
+
return None
|
|
153
|
+
if stacked.ndim != 2 or stacked.shape[1] == 0:
|
|
154
|
+
return None
|
|
155
|
+
if stacked.dtype != np.float64:
|
|
156
|
+
stacked = stacked.astype(np.float64, copy=False)
|
|
157
|
+
return stacked
|
|
158
|
+
|
|
159
|
+
def _cosine_distance_stacked(self, left_mat: np.ndarray, right_mat: np.ndarray) -> np.ndarray:
|
|
160
|
+
if left_mat.shape != right_mat.shape:
|
|
161
|
+
raise ValueError("Left and right matrices must have the same shape")
|
|
162
|
+
dots = np.sum(left_mat * right_mat, axis=1)
|
|
163
|
+
denom = np.sqrt(np.sum(left_mat * left_mat, axis=1)) * np.sqrt(np.sum(right_mat * right_mat, axis=1))
|
|
164
|
+
results = np.full(len(left_mat), np.nan, dtype=np.float64)
|
|
165
|
+
valid = denom > 0
|
|
166
|
+
results[valid] = 1 - dots[valid] / denom[valid]
|
|
167
|
+
return results
|
|
168
|
+
|
|
169
|
+
def _try_fast_distance(
|
|
170
|
+
self, left_arr: np.ndarray, right_arr: np.ndarray, row_present: np.ndarray, n: int
|
|
171
|
+
) -> Optional[np.ndarray]:
|
|
172
|
+
valid_idx = np.flatnonzero(row_present)
|
|
173
|
+
if len(valid_idx) == 0:
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
left_mat = self._stack_vectors(left_arr, valid_idx)
|
|
177
|
+
right_mat = self._stack_vectors(right_arr, valid_idx)
|
|
178
|
+
if left_mat is None or right_mat is None:
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
stacked_results = self._cosine_distance_stacked(left_mat, right_mat)
|
|
182
|
+
if row_present.all():
|
|
183
|
+
return stacked_results
|
|
184
|
+
|
|
185
|
+
results = np.full(n, np.nan, dtype=np.float64)
|
|
186
|
+
results[valid_idx] = stacked_results
|
|
187
|
+
return results
|
|
188
|
+
|
|
189
|
+
def _parse_vectors(self, left_arr: np.ndarray, right_arr: np.ndarray) -> tuple[list, list, np.ndarray]:
|
|
190
|
+
n = len(left_arr)
|
|
191
|
+
left_vecs: list[Optional[np.ndarray]] = [None] * n
|
|
192
|
+
right_vecs: list[Optional[np.ndarray]] = [None] * n
|
|
193
|
+
row_valid = np.zeros(n, dtype=bool)
|
|
194
|
+
for i, (left_value, right_value) in enumerate(zip(left_arr, right_arr)):
|
|
195
|
+
left_vec = self._to_float_vector(left_value)
|
|
196
|
+
right_vec = self._to_float_vector(right_value)
|
|
197
|
+
left_vecs[i] = left_vec
|
|
198
|
+
right_vecs[i] = right_vec
|
|
199
|
+
if left_vec is not None and right_vec is not None and left_vec.size > 0 and right_vec.size > 0:
|
|
200
|
+
row_valid[i] = True
|
|
201
|
+
return left_vecs, right_vecs, row_valid
|
|
202
|
+
|
|
203
|
+
def _masked_cosine_distance(
|
|
204
|
+
self, left_mat: np.ndarray, right_mat: np.ndarray, row_valid: np.ndarray
|
|
205
|
+
) -> np.ndarray:
|
|
206
|
+
results = self._cosine_distance_stacked(left_mat, right_mat)
|
|
207
|
+
if len(results) == len(row_valid):
|
|
208
|
+
results[~row_valid] = np.nan
|
|
209
|
+
return results
|
|
210
|
+
|
|
211
|
+
def _calculate_rowwise(
|
|
212
|
+
self, results: np.ndarray, indices: np.ndarray, left_vecs: list, right_vecs: list
|
|
213
|
+
) -> None:
|
|
214
|
+
for index in indices:
|
|
215
|
+
left_vec = left_vecs[index]
|
|
216
|
+
right_vec = right_vecs[index]
|
|
217
|
+
dot = np.sum(left_vec * right_vec)
|
|
218
|
+
denom = np.sqrt(np.sum(left_vec * left_vec)) * np.sqrt(np.sum(right_vec * right_vec))
|
|
219
|
+
if denom != 0:
|
|
220
|
+
results[index] = 1 - dot / denom
|
|
221
|
+
|
|
222
|
+
def _calculate_fallback_distance(
|
|
223
|
+
self, left_arr: np.ndarray, right_arr: np.ndarray, n: int, index: pd.Index
|
|
224
|
+
) -> pd.Series:
|
|
225
|
+
results = np.full(n, np.nan, dtype=np.float64)
|
|
226
|
+
left_vecs, right_vecs, row_valid = self._parse_vectors(left_arr, right_arr)
|
|
227
|
+
if not row_valid.any():
|
|
228
|
+
return pd.Series(results, index=index, dtype=np.float64)
|
|
229
|
+
|
|
230
|
+
valid_idx = np.flatnonzero(row_valid)
|
|
231
|
+
dim = left_vecs[valid_idx[0]].size
|
|
232
|
+
if not all(left_vecs[i].size == dim and right_vecs[i].size == dim for i in valid_idx):
|
|
233
|
+
self._calculate_rowwise(results, valid_idx, left_vecs, right_vecs)
|
|
234
|
+
return pd.Series(results, index=index, dtype=np.float64)
|
|
235
|
+
|
|
236
|
+
left_mat = np.zeros((n, dim), dtype=np.float64)
|
|
237
|
+
right_mat = np.zeros((n, dim), dtype=np.float64)
|
|
238
|
+
left_mat[valid_idx] = np.stack([left_vecs[i] for i in valid_idx])
|
|
239
|
+
right_mat[valid_idx] = np.stack([right_vecs[i] for i in valid_idx])
|
|
240
|
+
|
|
241
|
+
return pd.Series(self._masked_cosine_distance(left_mat, right_mat, row_valid), index=index, dtype=np.float64)
|
|
242
|
+
|
|
143
243
|
def calculate_binary(self, left: pd.Series, right: pd.Series) -> pd.Series:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def __norm(self, vector: pd.Series) -> pd.Series:
|
|
158
|
-
vector = vector.fillna(np.nan)
|
|
159
|
-
return np.sqrt(self.__dot(vector, vector))
|
|
244
|
+
n = len(left)
|
|
245
|
+
if n == 0:
|
|
246
|
+
return pd.Series(np.full(n, np.nan), index=left.index, dtype=np.float64)
|
|
247
|
+
|
|
248
|
+
row_present = left.notna().to_numpy() & right.notna().to_numpy()
|
|
249
|
+
left_arr = left.to_numpy()
|
|
250
|
+
right_arr = right.to_numpy()
|
|
251
|
+
|
|
252
|
+
fast_results = self._try_fast_distance(left_arr, right_arr, row_present, n)
|
|
253
|
+
if fast_results is not None:
|
|
254
|
+
return pd.Series(fast_results, index=left.index, dtype=np.float64)
|
|
255
|
+
|
|
256
|
+
return self._calculate_fallback_distance(left_arr, right_arr, n, left.index)
|
|
160
257
|
|
|
161
258
|
|
|
162
259
|
# Left for backward compatibility
|
|
@@ -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
|
-
|
|
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"
|
|
149
|
+
return f"date_diff_lists_{self.diff_unit}"
|
|
138
150
|
|
|
139
151
|
@classmethod
|
|
140
|
-
def from_formula(cls, formula: str) -> Optional["
|
|
141
|
-
if
|
|
142
|
-
return
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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=
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
190
|
-
results[i] = self.
|
|
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
|
|
201
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
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
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
|
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.156.dev3 → upgini-1.2.156.dev5}/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
|