diff --git a/docs/src/reference/index.md b/docs/src/reference/index.md index 596be48af..638b65420 100644 --- a/docs/src/reference/index.md +++ b/docs/src/reference/index.md @@ -44,6 +44,8 @@ Check the index on the left for a more detailed description of any symbol. | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | | [`tp.combine()`][temporian.combine] | Combines events from [`EventSets`][temporian.EventSet] with different samplings. | | [`tp.glue()`][temporian.glue] | Concatenates features from [`EventSets`][temporian.EventSet] with the same sampling. | +| [`EventSet.abs()`][temporian.EventSet.abs] | Computes the absolute value of the features. +| [`EventSet.add_index()`][temporian.EventSet.add_index] | Adds indexes to an [`EventSet`][temporian.EventSet]. | | [`EventSet.abs()`][temporian.EventSet.abs] | Computes the absolute value of the features. | | [`EventSet.add_index()`][temporian.EventSet.add_index] | Adds indexes to an [`EventSet`][temporian.EventSet]. | [`EventSet.arccos()`][temporian.EventSet.arccos] | Computes the inverse cosine of the features. @@ -70,6 +72,7 @@ Check the index on the left for a more detailed description of any symbol. | [`EventSet.propagate()`][temporian.EventSet.propagate] | Propagates feature values over a sub index. | | [`EventSet.rename()`][temporian.EventSet.rename] | Renames an [`EventSet`][temporian.EventSet]'s features and index. | | [`EventSet.resample()`][temporian.EventSet.resample] | Resamples an [`EventSet`][temporian.EventSet] at each timestamp of another [`EventSet`][temporian.EventSet]. | +| [`EventSet.round()`][temporian.EventSet.round] | Computes the round value of the features. | | [`EventSet.select()`][temporian.EventSet.select] | Selects a subset of features from an [`EventSet`][temporian.EventSet]. | | [`EventSet.select_index_values()`][temporian.EventSet.select_index_values] | Selects a subset of index values from an [`EventSet`][temporian.EventSet]. | | [`EventSet.set_index()`][temporian.EventSet.set_index] | Replaces the indexes in an [`EventSet`][temporian.EventSet]. diff --git a/docs/src/reference/temporian/operators/unary/round.md b/docs/src/reference/temporian/operators/unary/round.md new file mode 100644 index 000000000..fc0758981 --- /dev/null +++ b/docs/src/reference/temporian/operators/unary/round.md @@ -0,0 +1 @@ +::: temporian.EventSet.round \ No newline at end of file diff --git a/temporian/core/event_set_ops.py b/temporian/core/event_set_ops.py index 62fdda797..4ed8d3f51 100644 --- a/temporian/core/event_set_ops.py +++ b/temporian/core/event_set_ops.py @@ -1501,6 +1501,38 @@ def abs( return abs(self) + def __round__(self): + from temporian.core.operators.unary import round + + return round(input=self) + + def round( + self: EventSetOrNode, + ) -> EventSetOrNode: + """Rounds the values of an [`EventSet`][temporian.EventSet]'s features to the nearest integer. +only float types are allowed and the output. Output type wil be same as the input type + Example: + ```python + >>> a = tp.event_set( + ... timestamps=[1, 2, 3], + ... features={"M": [1.4, 2.6, 3.1], "N": [-1.9, -3.5, 5.8]}, + ... ) + >>> a.round() + indexes: ... + 'M': [1, 3, 3] + 'N': [-2, -4, 6] + ... + + ``` + + Returns: + EventSet with rounded feature values. + """ + from temporian.core.operators.unary import round + + return round(self) + + def add_index( self: EventSetOrNode, indexes: Union[str, List[str]] ) -> EventSetOrNode: diff --git a/temporian/core/operators/test/test_unary.py b/temporian/core/operators/test/test_unary.py index 0abe79bdc..b0ecea45c 100644 --- a/temporian/core/operators/test/test_unary.py +++ b/temporian/core/operators/test/test_unary.py @@ -99,7 +99,68 @@ def test_correct_notnan(self) -> None: ) assertOperatorResult(self, evset.notnan(), expected) - def test_correct_sin(self) -> None: + + def test_round_single_feature(self): + evset = event_set( + timestamps=[1, 2, 3], + features={"f": [1.1, -2.5, -3.9]}, + ) + expected = event_set( + timestamps=[1, 2, 3], + features={"f": [1.0, -3.0, -4.0]}, + same_sampling_as=evset, + ) + assertOperatorResult(self, evset.round(), expected) + assertOperatorResult(self, round(evset), expected) # __round__ magic + + def test_round_multiple_features(self): + evset = event_set( + timestamps=[1, 2], + features={"a": [10.5, 11.7], "b": [1.2, 2.9]}, + ) + expected = event_set( + timestamps=[1, 2], + features={"a": [11.0, 12.0], "b": [1.0, 3.0]}, + same_sampling_as=evset, + ) + assertOperatorResult(self, evset.round(), expected) + assertOperatorResult(self, round(evset), expected) # __round__ magic + + def test_round_non_accepted_types(self): + evset = event_set( + timestamps=[1, 2], + features={"a": ["10.5", 11.7], "b": [1, 2]}, + ) + with self.assertRaises(TypeError): + _ = evset.round() + + def test_round_float32(self): + evset = event_set( + timestamps=[1, 2], + features={"a": [10.5, 11.7], "b": [1.2, 2.9]}, + ) + expected = event_set( + timestamps=[1, 2], + features={"a": [11.0, 12.0], "b": [1.0, 3.0]}, + same_sampling_as=evset, + ) + assertOperatorResult(self, evset.round(), expected) + assertOperatorResult(self, round(evset), expected) # __round__ magic + + def test_round_float64(self): + evset = event_set( + timestamps=[1, 2], + features={"a": [10.5, 11.7], "b": [1.2, 2.9]}, + ) + expected = event_set( + timestamps=[1, 2], + features={"a": [11.0, 12.0], "b": [1.0, 3.0]}, + same_sampling_as=evset, + ) + assertOperatorResult(self, evset.round(), expected) + assertOperatorResult(self, round(evset), expected) # __round__ magic + + def test_correct_sin(self) -> None: evset = event_set( timestamps=[1, 2, 3, 4], features={"f": [0, np.pi / 2, np.pi, 3 * np.pi / 2]}, diff --git a/temporian/core/operators/unary.py b/temporian/core/operators/unary.py index dceb5525a..98435285f 100644 --- a/temporian/core/operators/unary.py +++ b/temporian/core/operators/unary.py @@ -182,6 +182,11 @@ def get_output_dtype(cls, feature_dtype: DType) -> DType: return feature_dtype +class RoundOperator(BaseUnaryOperator): + @classmethod + def op_key_definition(cls) -> str: + return "ROUND" + class SinOperator(BaseUnaryOperator): @classmethod def op_key_definition(cls) -> str: @@ -272,6 +277,7 @@ class ArcTanOperator(BaseUnaryOperator): def op_key_definition(cls) -> str: return "ARCTAN" + @classmethod def allowed_dtypes(cls) -> List[DType]: return [ @@ -289,6 +295,7 @@ def get_output_dtype(cls, feature_dtype: DType) -> DType: operator_lib.register_operator(NotNanOperator) operator_lib.register_operator(AbsOperator) operator_lib.register_operator(LogOperator) +operator_lib.register_operator(RoundOperator) operator_lib.register_operator(SinOperator) operator_lib.register_operator(CosOperator) operator_lib.register_operator(TanOperator) @@ -353,6 +360,16 @@ def log( @compile +def round( + input: EventSetOrNode, +) -> EventSetOrNode: + assert isinstance(input, EventSetNode) + + return RoundOperator( + input=input, + ).outputs["output"] + +@compile def sin( input: EventSetOrNode, ) -> EventSetOrNode: @@ -414,5 +431,6 @@ def arctan( assert isinstance(input, EventSetNode) return ArcTanOperator( + input=input, ).outputs["output"] diff --git a/temporian/implementation/numpy/operators/unary.py b/temporian/implementation/numpy/operators/unary.py index 9e0d111a1..242ab61d8 100644 --- a/temporian/implementation/numpy/operators/unary.py +++ b/temporian/implementation/numpy/operators/unary.py @@ -10,6 +10,7 @@ NotNanOperator, IsNanOperator, LogOperator, + RoundOperator, SinOperator, CosOperator, TanOperator, @@ -83,6 +84,11 @@ def _do_operation(self, feature: np.ndarray) -> np.ndarray: return np.log(feature) + +class RoundNumpyImplementation(BaseUnaryNumpyImplementation): + def _do_operation(self, feature: np.ndarray) -> np.ndarray: + return np.round(feature) + class SinNumpyImplementation(BaseUnaryNumpyImplementation): def _do_operation(self, feature: np.ndarray) -> np.ndarray: return np.sin(feature) @@ -129,6 +135,9 @@ def _do_operation(self, feature: np.ndarray) -> np.ndarray: LogOperator, LogNumpyImplementation ) implementation_lib.register_operator_implementation( + + RoundOperator, RoundNumpyImplementation + SinOperator, SinNumpyImplementation ) implementation_lib.register_operator_implementation(