Skip to content

[ENH] add a difference transformer to series transformations #2729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8c07ea3
add difference transformer to series transformations
TinaJin0228 Apr 6, 2025
321fdc2
add myself to .all-contributorsrc
TinaJin0228 Apr 6, 2025
8f78ec9
small modification
TinaJin0228 Apr 6, 2025
8b79897
Merge branch 'main' into feat/diff-transformer
TinaJin0228 Apr 6, 2025
606110c
modify according to reviews
TinaJin0228 Apr 13, 2025
c097579
Merge branch 'main' into feat/diff-transformer
TinaJin0228 Apr 14, 2025
174e126
Merge branch 'main' into feat/diff-transformer
MatthewMiddlehurst Apr 30, 2025
e4f84ae
Merge branch 'main' into feat/diff-transformer
TinaJin0228 May 12, 2025
73b8799
Merge branch 'main' into feat/diff-transformer
TonyBagnall May 16, 2025
0f1e79a
[ENH] add informational tags back to estimator docs (#2652)
inclinedadarsh May 17, 2025
a2e82d7
[DOC] Documentation improvement of BaseSeriesEstimator and BaseAeonEs…
kevinzb56 May 18, 2025
310ae99
[ENH] HydraTransformer Output changed (#2656)
lucifer4073 May 18, 2025
e31989e
[DOC] Improved Hidalgo Segmentation Notebook (#2616)
kavya-r30 May 18, 2025
62d1e91
new devs and workflow consolidation (#2797)
MatthewMiddlehurst May 18, 2025
3b861c0
all branches (#2809)
MatthewMiddlehurst May 18, 2025
d65c629
Automated `pre-commit` hook update (#2820)
aeon-actions-bot[bot] May 19, 2025
5741567
[MNT] Bump crs-k/stale-branches in the github-actions group (#2821)
dependabot[bot] May 19, 2025
1ebd5e4
fix: indexing in kdtw (#2826)
SebastianSchmidl May 20, 2025
1406526
[ENH] Added test cases for feature based clustering (#2690)
Ramana-Raja May 21, 2025
85ee3d9
[DOC] Fix inconsistent double backticks in updated similarity_search…
adityagh006 May 21, 2025
43c959b
delete some descriptions
TinaJin0228 May 23, 2025
b915120
Merge branch 'main' into feat/diff-transformer
SebastianSchmidl May 23, 2025
e631926
modification to _maintainer_
TinaJin0228 May 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -2710,6 +2710,16 @@
"contributions": [
"doc"
]
},
{
"login": "TinaJin0228",
"name": "Tina Jin",
"avatar_url": "https://avatars.githubusercontent.com/TinaJin0228",
"profile": "https://github.com/TinaJin0228",
"contributions": [
"code",
"doc"
]
}
],
"commitType": "docs"
Expand Down
2 changes: 2 additions & 0 deletions aeon/transformations/series/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"SIVSeriesTransformer",
"PCASeriesTransformer",
"WarpingSeriesTransformer",
"DifferenceTransformer",
]

from aeon.transformations.series._acf import (
Expand All @@ -32,6 +33,7 @@
from aeon.transformations.series._boxcox import BoxCoxTransformer
from aeon.transformations.series._clasp import ClaSPTransformer
from aeon.transformations.series._dft import DFTSeriesTransformer
from aeon.transformations.series._diff import DifferenceTransformer
from aeon.transformations.series._dobin import Dobin
from aeon.transformations.series._exp_smoothing import ExpSmoothingSeriesTransformer
from aeon.transformations.series._gauss import GaussSeriesTransformer
Expand Down
92 changes: 92 additions & 0 deletions aeon/transformations/series/_diff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import numpy as np

from aeon.transformations.series.base import BaseSeriesTransformer

__maintainer__ = ["TinaJin0228"]
__all__ = ["DifferenceTransformer"]


class DifferenceTransformer(BaseSeriesTransformer):
"""
Calculates the n-th order difference of a time series.

Transforms a time series X into a series Y representing the difference
calculated `order` times.

The time series are supposed to be all in rows,
with shape (n_channels, n_timepoints)

- Order 1: Y[t] = X[t] - X[t-1]
- Order 2: Y[t] = (X[t] - X[t-1]) - (X[t-1] - X[t-2]) = X[t] - 2*X[t-1] + X[t-2]
- ... and so on.

The transformed series will be shorter than the input series by `order`
elements along the time axis.

Parameters
----------
order : int, default=1
The order of differencing. Must be a positive integer.

Notes
-----
This transformer assumes the input series does not contain NaN values where
the difference needs to be computed.

Examples
--------
>>> import numpy as np
>>> from aeon.transformations.series._diff import DifferenceTransformer
>>> X1 = np.array([[1, 3, 2, 5, 4, 7, 6, 9, 8, 10]]) # Shape (1, 10)
>>> dt = DifferenceTransformer()
>>> Xt1 = dt.fit_transform(X1)
>>> print(Xt1) # Shape (1, 9)
[[ 2 -1 3 -1 3 -1 3 -1 2]]

>>> X2 = np.array([[1, 3, 2, 5, 4, 7, 6, 9, 8, 10]]) # Shape (1, 10)
>>> dt2 = DifferenceTransformer(order=2)
>>> Xt2 = dt2.fit_transform(X2)
>>> print(Xt2) # Shape (1, 8)
[[-3 4 -4 4 -4 4 -4 3]]

>>> X3 = np.array([[1, 2, 3, 4, 5], [5, 4, 3, 2, 1]]) # Shape (2, 5)
>>> dt = DifferenceTransformer()
>>> Xt3 = dt.fit_transform(X3)
>>> print(Xt3) # Shape (2, 4)
[[ 1 1 1 1]
[-1 -1 -1 -1]]
"""

_tags = {
"capability:multivariate": True,
"X_inner_type": "np.ndarray",
"fit_is_empty": True,
}

def __init__(self, order=1):
self.order = order
super().__init__(axis=1)

def _transform(self, X, y=None):
"""
Perform the n-th order differencing transformation.

Parameters
----------
X : Time series to transform. With shape (n_channels, n_timepoints).
y : ignored argument for interface compatibility

Returns
-------
Xt : np.ndarray
"""
if not isinstance(self.order, int) or self.order < 1:
raise ValueError(
f"`order` must be a positive integer, but got {self.order}"
)

diff_X = np.diff(X, n=self.order, axis=1)

Xt = diff_X

return Xt
37 changes: 37 additions & 0 deletions aeon/transformations/series/tests/test_diff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Tests for Difference transformation."""

import numpy as np

from aeon.transformations.series._diff import DifferenceTransformer


def test_diff():
"""Tests basic first and second order differencing."""
X = np.array([[1.0, 4.0, 9.0, 16.0, 25.0, 36.0]])

dt1 = DifferenceTransformer(order=1)
Xt1 = dt1.fit_transform(X)
expected1 = np.array([[3.0, 5.0, 7.0, 9.0, 11.0]])

np.testing.assert_allclose(
Xt1, expected1, equal_nan=True, err_msg="Value mismatch for order 1"
)

dt2 = DifferenceTransformer(order=2)
Xt2 = dt2.fit_transform(X)
expected2 = np.array([[2.0, 2.0, 2.0, 2.0]])

np.testing.assert_allclose(
Xt2, expected2, equal_nan=True, err_msg="Value mismatch for order 2"
)

Y = np.array([[1, 2, 3, 4], [5, 3, 1, 8]])

Yt1 = dt1.fit_transform(Y)
expected3 = np.array([[1, 1, 1], [-2, -2, 7]])
np.testing.assert_allclose(
Yt1,
expected3,
equal_nan=True,
err_msg="Value mismatch for order 1,multivariate",
)