Skip to main content

tsfresh-rs

Fast, drop-in time series feature extraction for Python, powered by Rust.

CI PyPI Python 3.10 to 3.14 License: MIT

What it is

A machine that runs for a week produces a million sensor readings and no columns. Most models want columns: one row per machine, one column per property of its signal. Turning the first into the second is time series feature extraction, and tsfresh is the standard Python library for it - it computes 783 such properties per signal, from the mean to the Dickey-Fuller test statistic, then runs hypothesis tests to tell you which ones actually relate to your target.

It is also slow enough that people give up on it. A comprehensive extraction costs roughly 290 ms per series, so a hundred thousand series is most of a day.

tsfresh-rs is that library reimplemented in Rust. Same functions, same arguments, same 783 columns under the same names in the same order - about 100x faster.

What it does

Raw readings in, one row per series out:

import numpy as np
import pandas as pd
import tsfresh_rs as tsfresh

rng = np.random.default_rng(0)
rows = []
for machine_id in range(20):
    signal = rng.standard_normal(100)
    if machine_id % 2:                       # half the machines drift
        signal += 0.03 * np.arange(100)
    rows.append(pd.DataFrame(
        {"id": machine_id, "time": np.arange(100), "vibration": signal}
    ))
df = pd.concat(rows, ignore_index=True)
   id  time  vibration
0   0     0   0.125730
1   0     1  -0.132105
2   0     2   0.640423
...
[2000 rows x 3 columns]

One call turns those 2,000 readings into a feature matrix:

X = tsfresh.extract_features(df, column_id="id", column_sort="time")
X.shape
(20, 783)

   vibration__mean  vibration__standard_deviation  vibration__linear_trend__attr_"slope"
0           0.0811                         0.9621                                 0.0015
1           1.4344                         1.2601                                 0.0285
2          -0.1380                         1.1156                                -0.0030
3           1.4460                         1.2784                                 0.0306
4           0.0120                         1.0836                                -0.0040
5           1.4832                         1.1311                                 0.0241

783 columns is deliberately more than you need. If you have labels, a second call keeps only the columns that are statistically related to them:

from tsfresh_rs.utilities.dataframe_functions import impute

y = pd.Series([mid % 2 for mid in range(20)])   # which machines drifted
impute(X)                                        # selection rejects NaN
selected = tsfresh.select_features(X, y)
selected.shape
(20, 124)

That matrix goes straight into scikit-learn, or anything else that takes a DataFrame.

Install

pip install tsfresh-rs

Wheels for Linux, macOS and Windows. Python 3.10 through 3.14 from a single abi3 wheel per platform, and nothing to compile.

Already using tsfresh?

Change the import. That is the whole migration:

- import tsfresh
+ import tsfresh_rs as tsfresh

Same functions, same arguments, same 783 feature columns, same column names in the same order - verified by 478 tests that run both libraries on the same input and compare every value, including which inputs each one refuses.

If you cannot change the import - a pipeline that pulls in tsfresh by name deep inside a dependency - alias the package instead:

import tsfresh_rs
tsfresh_rs.install()   # before anything imports `tsfresh`

import tsfresh         # this is now tsfresh_rs

It refuses rather than half-patching the module graph if the real tsfresh has already been imported.

How much faster

End-to-end extraction speedup of tsfresh-rs over tsfresh: 93x to 141x across six workloads.

workload tsfresh tsfresh-rs speedup
10 series × 500 pts 2.94 s 0.0278 s 106x
20 series × 500 pts 5.72 s 0.0464 s 123x
50 series × 500 pts 14.18 s 0.1007 s 141x
100 series × 500 pts 27.23 s 0.1951 s 140x

Two things are slow in the reference, and fixing only the obvious one gets you a fraction of the win. The calculators themselves are slow - rewriting those in Rust is worth about 17x. But most of a comprehensive extraction is not the calculators at all: it is a Python call and a pandas groupby/apply per series per feature. So this package does not call calculators one at a time. It flattens every series into one contiguous buffer, compiles the whole feature plan once, and makes a single call into Rust with the GIL released. Owning that loop is what turns 17x into 120x.

Full tables - longer series, n_jobs, per calculator, and the preset that exists to avoid the cost - are in docs/BENCHMARKS.md.

What it adds: feature_timings

tsfresh ships EfficientFCParameters, a preset that drops approximate_entropy and sample_entropy because they are expensive. That is a guess - a judgement the maintainers made once, on their data. On a 500-point series those two really are 62% of the run. On a 50-point series they are nearly free. On a 20,000-point series something else dominates entirely.

feature_timings measures it on your data:

import tsfresh_rs as tsfresh

timings = tsfresh.feature_timings(df, column_id="id", column_sort="time")
print(timings.head(6)[["feature", "columns", "seconds", "pct_of_total"]])
#                 feature  columns   seconds  pct_of_total
#     approximate_entropy        5  0.139937     60.287962
# augmented_dickey_fuller        3  0.032445     13.977916
#          sample_entropy        1  0.018846      8.119415
#        change_quantiles       60  0.007768      3.346718
#        number_cwt_peaks        2  0.007093      3.055826
#          ar_coefficient       11  0.006635      2.858552

The shares are exhaustive — all 74 features, summing to 100% — so nothing is hiding outside the report.

And drop_slowest turns that report into a feature set:

from tsfresh_rs.profiling import drop_slowest

cheap = drop_slowest(tsfresh.ComprehensiveFCParameters(), timings, budget_pct=90)
X = tsfresh.extract_features(df, default_fc_parameters=cheap,
                             column_id="id", column_sort="time")

tsfresh has no equivalent. The question "which of these 783 columns am I paying for?" currently has no answer other than deleting features and re-timing by hand.

Is it actually the same?

That is the only question that matters for a drop-in, so it is the one the test suite is built around.

  • 478 tests, almost all differential against tsfresh on the same input, comparing every value - and every refusal, so an input the reference rejects is rejected here too.
  • 250 randomised fuzz cases over length, scale, offset, tie density and degeneracy. This found four real defects during development, including a wrong Mexican-hat amplitude that scaled all 60 cwt_coefficients columns by 1.3025 - a uniform error that looks entirely plausible in isolation.
  • API coverage is asserted mechanically: every calculator in the reference must exist here with the same attributes, because those attributes are what define the presets.
  • Reference quirks are reproduced deliberately. fft_aggregated's kurtosis has a term the standardised fourth moment does not want; ComprehensiveFCParameters builds mean_n_absolute_max from a dict literal with three copies of one key, so two of its three intended features have never existed. Both are matched bug-for-bug, because a drop-in that quietly fixes a feature changes numbers people have already trained on.

A handful of values legitimately differ, and a few are more accurate here than in the reference. Every one is documented and pinned by a test in docs/COMPATIBILITY.md.

Limitations

Stated plainly, because a drop-in that hides its gaps is worse than one that does not have them.

  • matrix_profile is unavailable, exactly as in the reference. The matrixprofile package is unmaintained and does not build on current Python, so tsfresh ships with this feature disabled and excluded from ComprehensiveFCParameters. This mirrors that, including the ImportError.
  • select_features is not accelerated. It is linear in the number of features with one cheap hypothesis test each — not the bottleneck this package exists to fix — so it runs in Python. n_jobs and chunksize are accepted and ignored there.
  • chunksize, distributor and the profile* arguments describe tsfresh's multiprocessing pipeline, which this implementation does not have. They are accepted for signature compatibility and ignored, with a warning. The utilities.distribution classes exist so that code importing them keeps working, but extract_features does not route through them.
  • tsfresh.__version__ reports this package's version after install(), not a tsfresh one, so code gating on tsfresh.__version__ >= "0.20" will take the wrong branch. Claiming to be 0.21.2 would fix that one check and lie to every other; the API level being emulated is published separately as tsfresh_rs.__tsfresh_version__.
  • profile=True no longer answers "which calculator is slow". A cProfile trace of an extraction here shows one opaque call into Rust. feature_timings is the replacement, and it measures what the profiler used to.
  • augmented_dickey_fuller is only 4x faster. Its cost is a lag-selection search over many OLS fits, and the reference already spends that time inside compiled LAPACK.

Development

pip install maturin pytest numpy pandas scipy tsfresh mpmath statsmodels
maturin build --release --out dist && pip install --no-index --find-links dist tsfresh-rs
pytest tests/ -q
python bench/bench.py

To reproduce the older-reference environment the version table describes — the one where three feature columns legitimately differ — and check that the suite skips exactly those:

uv venv --python 3.10 /tmp/old && uv pip install --python /tmp/old/bin/python     pytest numpy pandas scipy tsfresh mpmath statsmodels
uv pip install --python /tmp/old/bin/python --no-deps --find-links dist tsfresh-rs
/tmp/old/bin/python -m pytest tests/ -q -rs

That resolves to numpy 2.2, pandas 2.3, SciPy 1.15 and PyWavelets 1.8, and gives 411 passed, 3 skipped.

Licence and credit

MIT, the same licence as tsfresh.

This is a reimplementation of tsfresh by Maximilian Christ and Blue Yonder GmbH, whose API, feature definitions and output semantics it deliberately reproduces. If you use this in research, cite their paper:

Christ, M., Braun, N., Neuffer, J. and Kempa-Liehr A.W. (2018). Time Series FeatuRe Extraction on basis of Scalable Hypothesis tests (tsfresh — A Python package). Neurocomputing 307 (2018) 72-77.

Metadata

Release files for tsfresh-rs 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tsfresh-rs 0.1.1
File Size Uploaded
tsfresh_rs-0.1.1.tar.gz 176.8 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for tsfresh-rs 0.1.1
File
tsfresh_rs-0.1.1-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
tsfresh_rs-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
tsfresh_rs-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
tsfresh_rs-0.1.1-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
tsfresh_rs-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 3.8 MB

Release files / tsfresh_rs-0.1.1.tar.gz

Download URL tsfresh_rs-0.1.1.tar.gz
Size 176.8 kB
Tags Source
SHA-256 checksum
How to use checksums
612ec7e441b788806fa8610189323afeda474c99964a28f5ec1f28f5232a53d8
BLAKE2b-256 checksum
How to use checksums
f0767472d5f74cdb4d343ce40046aab50140775d0cd85477ed9cc35ad8771f8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / tsfresh_rs-0.1.1-cp310-abi3-win_amd64.whl

Download URL tsfresh_rs-0.1.1-cp310-abi3-win_amd64.whl
Size 706.4 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
c7ce963ed07a9439142f0a3b588e744cc401a5f2c4d553db3222c734abdf9ff5
BLAKE2b-256 checksum
How to use checksums
0ee7bc073db27b191a05327d4e4a4aa22f2baf6177165b996e0df9aa43ebabfc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / tsfresh_rs-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL tsfresh_rs-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 842.4 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
2c5452fb528adf3828e2a5e390ab2bf5b07c3ccb02deb670b29930e560569f92
BLAKE2b-256 checksum
How to use checksums
4e17624b4832ad9aa259f4cf96ea182b9c190fd0aad5c0188d082eeaba99e5ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / tsfresh_rs-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL tsfresh_rs-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 670.0 kB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
0e5fa597a10afdfc9462d767b08bdd0baa7c53382e2b1671c7491710848c2bef
BLAKE2b-256 checksum
How to use checksums
37a276a2bff01dc0ee77bf4249acc45d92ccade1183f1c2ed5dad7c193c757fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / tsfresh_rs-0.1.1-cp310-abi3-macosx_11_0_arm64.whl

Download URL tsfresh_rs-0.1.1-cp310-abi3-macosx_11_0_arm64.whl
Size 630.8 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
c929e3288d8bdf295ba4bcf448fcef274c66eb45ce78c148c63e8a4a685c578e
BLAKE2b-256 checksum
How to use checksums
6379f60db490e3e65cfef7bf831167d256bf57885f55cf66ed3f27e9b28345b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / tsfresh_rs-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl

Download URL tsfresh_rs-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl
Size 762.6 kB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
8b4500a645afd73bbe02dfd68de47f9ace01a34e16c3149336bd81e9e286c3a8
BLAKE2b-256 checksum
How to use checksums
86f5d237585e46a51f541dc8aff042b947f5e2db04c49b1899069e0e43a0de75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

6 release files

0.1.0

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page