Time series downsampling in rust
Project Links
Meta
Author: Jeroen Van Der Donckt
Requires Python: >=3.8
Classifiers
Intended Audience
- Developers
License
- OSI Approved :: MIT License
Programming Language
- Python :: 3
- Python :: 3.8
- Python :: 3.9
- Python :: 3.10
- Python :: 3.11
- Python :: 3.12
- Python :: 3.13
Operating System
- POSIX
- MacOS :: MacOS X
- Microsoft :: Windows
tsdownsample
Extremely fast time series downsampling ๐ for visualization, written in Rust.
Features โจ
- Fast: written in rust with PyO3 bindings
- leverages optimized argminmax - which is SIMD accelerated with runtime feature detection
- scales linearly with the number of data points
- multithreaded with Rayon (in Rust)
Why we do not use Python multiprocessing
Citing the PyO3 docs on parallelism:
CPython has the infamous Global Interpreter Lock, which prevents several threads from executing Python bytecode in parallel. This makes threading in Python a bad fit for CPU-bound tasks and often forces developers to accept the overhead of multiprocessing.
In Rust - which is a compiled language - there is no GIL, so CPU-bound tasks can be parallelized (with Rayon) with little to no overhead.
- Efficient: memory efficient
- works on views of the data (no copies)
- no intermediate data structures are created
- Flexible: works on any type of data
- supported datatypes are
- for
x:f32,f64,i16,i32,i64,u16,u32,u64,datetime64,timedelta64 - for
y:f16,f32,f64,i8,i16,i32,i64,u8,u16,u32,u64,datetime64,timedelta64,bool
!! ๐
In contrast with all other data types above,f16argminmax is 200-300x faster than numpyf16is *not* hardware supported (i.e., no instructions for f16) by most modern CPUs!!
๐ Programming languages facilitate support for this datatype by either (i) upcasting to f32 or (ii) using a software implementation.
๐ก As for argminmax, only comparisons are needed - and thus no arithmetic operations - creating a symmetrical ordinal mapping fromf16toi16is sufficient. This mapping allows to use the hardware supported scalar and SIMDi16instructions - while not producing any memory overhead ๐
More details are described in argminmax PR #1. - for
- supported datatypes are
- Easy to use: simple & flexible API
Install
pip install tsdownsample
Usage
from tsdownsample import MinMaxLTTBDownsampler
import numpy as np
# Create a time series
y = np.random.randn(10_000_000)
x = np.arange(len(y))
# Downsample to 1000 points (assuming constant sampling rate)
s_ds = MinMaxLTTBDownsampler().downsample(y, n_out=1000)
# Select downsampled data
downsampled_y = y[s_ds]
# Downsample to 1000 points using the (possible irregularly spaced) x-data
s_ds = MinMaxLTTBDownsampler().downsample(x, y, n_out=1000)
# Select downsampled data
downsampled_x = x[s_ds]
downsampled_y = y[s_ds]
Downsampling algorithms & API
Downsampling API ๐
Each downsampling algorithm is implemented as a class that implements a downsample method.
The signature of the downsample method:
downsample([x], y, n_out, **kwargs) -> ndarray[uint64]
Arguments:
xis optionalxandyare both positional argumentsn_outis a mandatory keyword argument that defines the number of output values***kwargsare optional keyword arguments (see table below):parallel: whether to use multi-threading (default:False)
โ The max number of threads can be configured with theTSDOWNSAMPLE_MAX_THREADSENV var (e.g.os.environ["TSDOWNSAMPLE_MAX_THREADS"] = "4")- ...
Returns: a ndarray[uint64] of indices that can be used to index the original data.
*When there are gaps in the time series, fewer than n_out indices may be returned.
Downsampling algorithms ๐
The following downsampling algorithms (classes) are implemented:
| Downsampler | Description | **kwargs |
|---|---|---|
MinMaxDownsampler |
selects the min and max value in each bin | parallel |
M4Downsampler |
selects the min, max, first and last value in each bin | parallel |
LTTBDownsampler |
performs the Largest Triangle Three Buckets algorithm | parallel |
MinMaxLTTBDownsampler |
(new two-step algorithm ๐) first selects n_out * minmax_ratio min and max values, then further reduces these to n_out values using the Largest Triangle Three Buckets algorithm |
parallel, minmax_ratio* |
*Default value for minmax_ratio is 4, which is empirically proven to be a good default. More details here: https://arxiv.org/abs/2305.00332
Handling NaNs
This library supports two NaN-policies:
- Omit
NaNs (NaNs are ignored during downsampling). - Return index of first
NaNonce there is at least one present in the bin of the considered data.
Omit NaNs |
Return NaNs |
|---|---|
MinMaxDownsampler |
NaNMinMaxDownsampler |
M4Downsampler |
NaNM4Downsampler |
MinMaxLTTBDownsampler |
NaNMinMaxLTTBDownsampler |
LTTBDownsampler |
Note that NaNs are not supported for
x-data.
Limitations & assumptions ๐จ
Assumes;
x-data is (non-strictly) monotonic increasing (i.e., sorted)- no
NaNs inx-data
๐ค Jeroen Van Der Donckt
0.1.4.1
Jan 29, 2025
0.1.4.1rc0
Jan 29, 2025
0.1.4
Jan 28, 2025
0.1.3
Feb 02, 2024
0.1.3rc2
Jan 15, 2024
0.1.3rc1
Jan 03, 2024
0.1.2
Apr 23, 2023
0.1.2a1
Apr 14, 2023
0.1.2a0
Apr 12, 2023
0.1.1
Jan 30, 2023
0.1.0
Jan 17, 2023
0.1.0a7
Jan 16, 2023
0.1.0a6
Dec 29, 2022
0.1.0a5
Dec 01, 2022
0.1.0a4
Nov 27, 2022
0.1.0a3
Nov 26, 2022
0.1.0a2
Nov 25, 2022
0.1.0a1
Nov 25, 2022
0.1.0a0
Nov 22, 2022
Wheel compatibility matrix
Files in release
tsdownsample-0.1.4.1-cp310-cp310-macosx_10_12_x86_64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp310-cp310-macosx_11_0_arm64.whl (1.1MiB)
tsdownsample-0.1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl (1.3MiB)
tsdownsample-0.1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp310-cp310-manylinux_2_24_armv7l.whl (1.2MiB)
tsdownsample-0.1.4.1-cp310-cp310-manylinux_2_24_ppc64le.whl (1.2MiB)
tsdownsample-0.1.4.1-cp310-cp310-manylinux_2_24_s390x.whl (1.4MiB)
tsdownsample-0.1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl (1.5MiB)
tsdownsample-0.1.4.1-cp310-cp310-win32.whl (755.4KiB)
tsdownsample-0.1.4.1-cp310-cp310-win_amd64.whl (1009.9KiB)
tsdownsample-0.1.4.1-cp311-cp311-macosx_10_12_x86_64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp311-cp311-macosx_11_0_arm64.whl (1.1MiB)
tsdownsample-0.1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl (1.3MiB)
tsdownsample-0.1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp311-cp311-manylinux_2_24_armv7l.whl (1.2MiB)
tsdownsample-0.1.4.1-cp311-cp311-manylinux_2_24_ppc64le.whl (1.2MiB)
tsdownsample-0.1.4.1-cp311-cp311-manylinux_2_24_s390x.whl (1.4MiB)
tsdownsample-0.1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl (1.5MiB)
tsdownsample-0.1.4.1-cp311-cp311-win32.whl (755.4KiB)
tsdownsample-0.1.4.1-cp311-cp311-win_amd64.whl (1009.9KiB)
tsdownsample-0.1.4.1-cp312-cp312-macosx_10_12_x86_64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp312-cp312-macosx_11_0_arm64.whl (1.1MiB)
tsdownsample-0.1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl (1.3MiB)
tsdownsample-0.1.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp312-cp312-manylinux_2_24_armv7l.whl (1.2MiB)
tsdownsample-0.1.4.1-cp312-cp312-manylinux_2_24_ppc64le.whl (1.2MiB)
tsdownsample-0.1.4.1-cp312-cp312-manylinux_2_24_s390x.whl (1.4MiB)
tsdownsample-0.1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl (1.5MiB)
tsdownsample-0.1.4.1-cp312-cp312-win32.whl (749.6KiB)
tsdownsample-0.1.4.1-cp312-cp312-win_amd64.whl (1005.7KiB)
tsdownsample-0.1.4.1-cp313-cp313-macosx_10_12_x86_64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp313-cp313-macosx_11_0_arm64.whl (1.1MiB)
tsdownsample-0.1.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl (1.3MiB)
tsdownsample-0.1.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp313-cp313-manylinux_2_24_armv7l.whl (1.2MiB)
tsdownsample-0.1.4.1-cp313-cp313-manylinux_2_24_ppc64le.whl (1.2MiB)
tsdownsample-0.1.4.1-cp313-cp313-manylinux_2_24_s390x.whl (1.4MiB)
tsdownsample-0.1.4.1-cp313-cp313-musllinux_1_1_aarch64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp313-cp313-musllinux_1_1_x86_64.whl (1.5MiB)
tsdownsample-0.1.4.1-cp313-cp313-win32.whl (749.9KiB)
tsdownsample-0.1.4.1-cp313-cp313-win_amd64.whl (1005.1KiB)
tsdownsample-0.1.4.1-cp38-cp38-macosx_10_12_x86_64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp38-cp38-macosx_11_0_arm64.whl (1.1MiB)
tsdownsample-0.1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl (1.3MiB)
tsdownsample-0.1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp38-cp38-manylinux_2_24_armv7l.whl (1.2MiB)
tsdownsample-0.1.4.1-cp38-cp38-manylinux_2_24_ppc64le.whl (1.2MiB)
tsdownsample-0.1.4.1-cp38-cp38-manylinux_2_24_s390x.whl (1.4MiB)
tsdownsample-0.1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl (1.5MiB)
tsdownsample-0.1.4.1-cp38-cp38-win32.whl (755.7KiB)
tsdownsample-0.1.4.1-cp38-cp38-win_amd64.whl (1009.8KiB)
tsdownsample-0.1.4.1-cp39-cp39-macosx_10_12_x86_64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp39-cp39-macosx_11_0_arm64.whl (1.1MiB)
tsdownsample-0.1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2MiB)
tsdownsample-0.1.4.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl (1.3MiB)
tsdownsample-0.1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp39-cp39-manylinux_2_24_armv7l.whl (1.2MiB)
tsdownsample-0.1.4.1-cp39-cp39-manylinux_2_24_ppc64le.whl (1.2MiB)
tsdownsample-0.1.4.1-cp39-cp39-manylinux_2_24_s390x.whl (1.4MiB)
tsdownsample-0.1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl (1.3MiB)
tsdownsample-0.1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl (1.5MiB)
tsdownsample-0.1.4.1-cp39-cp39-win32.whl (755.7KiB)
tsdownsample-0.1.4.1-cp39-cp39-win_amd64.whl (1010.2KiB)
tsdownsample-0.1.4.1.tar.gz (542.9KiB)
Extras:
None
Dependencies:
numpy