reducers
Reduction functions + Rust(rs), shortname rd.
Rust-backed reduction functions for NumPy arrays - plain (numpy-like) and NaN-aware.
- Full documentation: https://ysbach.github.io/reducers/
- Rust API reference: https://docs.rs/reducers
The Goal of this toy project was:
- much faster than numpy in many use cases,
- much faster than bottleneck in many use cases, and
- especially maximum performance for median and variance calculations, which are often bottlenecks in data processing pipelines.
reducers might be slower than numpy or bottleneck for small arrays. However, the most time-consuming reductions like large arrays or deep stacks, median, percentile or quantile, var and std are frequently several times (>100 times for nanpercentiles) faster than numpy and bottleneck.
Install
pip install reducers
For Rust crate use:
[dependencies]
reducers = "<version>"
After Installation
Run the autotuner once on your machine where reducers will run:
python -m reducers.autotuner
It saves parallel-grain settings for that CPU and workload profile. Future
import reducers calls apply those settings automatically. The built-in
defaults are still valid; use python -m reducers.autotuner --reset to remove
the saved tuning file and return to them.
import numpy as np
import reducers as rd
a = np.array([1.0, 2.0, np.nan, np.inf, 5.0])
rd.mean(a) # nan: plain reducers propagate NaN/inf
rd.nanmean(a) # inf: skip NaN, keep inf
rd.nanmean(a, ignore_inf=True) # finite-only
rd.nanminmax(a) # one fused 1-D scan for nanmin + nanmax
rd.nanpercentile(a, [16, 50, 84])
Axis reductions cover the layouts this package optimizes:
rng = np.random.default_rng(20250311)
stack = rng.normal(size=(31, 256, 256)).astype("f4")
rows = rng.normal(size=(256, 256, 31)).astype("f4")
rd.nanmedian(stack, axis=0) # stack reduction -> shape (256, 256)
rd.nanmean(rows, axis=-1) # contiguous trailing-axis reduction
- For
[nan]varand[nan]std,return_mean=Truereturns the already-computed mean with the variance or standard deviation to avoid duplicate work when both are needed. [nan]sum(a, weights=w)can do similar:return_sum_weights=Trueandreturn_unweighted_sum=Trueexpose quantities already available during the fused weighted scan, avoiding separatesum(a * w),sum(w), orsum(a)passes when a caller needs them together.
std, mean = rd.nanstd(a, ddof=1, return_mean=True)
weighted_sum, sum_of_weights = rd.nansum(a, weights=w, return_sum_weights=True)
weighted_sum, unweighted_sum = rd.nansum(a, weights=w, return_unweighted_sum=True)
weighted_sum, unweighted_sum, sum_of_weights = rd.nansum(
a, weights=w, return_unweighted_sum=True, return_sum_weights=True
)
Dual use: the kernel modules are pure Rust (no PyO3/NumPy) and usable as a crate.
Unweighted mean and variance recover representable results after intermediate overflow; see numerical behavior for limits and performance.
The Rust sigma_clip module provides cumulative sigma clipping over slices,
with reusable caller-owned workspace, independent rejection/dispersion centers,
rollback policies, and optional clipped mean or median. Defaults are nkeep=0
and revert_on_nkeep=false, making survivor rollback opt-in. See the
Rust API and
performance notes.
The Rust reject module provides IRAF imcombine-style per-sample rejection
(ccdclip, linearclip, minmax, pclip) over one slice at a time, with the
same reusable workspace pattern. It is shared with
imcombiners and has no Python binding.
Python exposes sigclip/sigclip_1d, mask-only variants, fused
sigclip_combine/sigclip_combine_1d mean/median calls, restoration flags,
grow_mask, and reusable SigClip settings. They call the same Rust engine:
values = np.array([1., 2., 3., 4., 100.])
rd.sigclip_mask_1d(values, sigma=2) # [False, False, False, False, True]
rd.sigclip_combine_1d(values, combine="mean", sigma=2) # 2.5
Maximum-performance Python calls
For fixed production hot loops, import the low-level Python API as rdl:
import reducers.lowlevel as rdl
The rdl functions call the same Rust kernels but skip the high-level Python
normalization layer. Weighted hot loops can choose the narrow fused primitive
for the output terms they actually need:
weighted_sum = rdl.weighted_sum_only_skip_nonfinite(a, w)
weighted_sum, sum_weights = rdl.weighted_sum_and_weights_skip_nonfinite(a, w)
weighted_sum, sum_weights, unweighted_sum = rdl.weighted_sum_skip_nonfinite(a, w)
average = rdl.weighted_average_skip_nonfinite(a, w)
See the documentation for details on achieving maximum performance.
Current limits
-
axismay beNone(default, whole-array),0or-1(identical toa.ndim - 1); other axes raiseNotImplementedError. This keeps hidden transpose/copy costs out of the API and lets the Rust kernels specialize for the supported layouts. -
NumPy-like subset: There are many unsupported parameters like
out,keepdims,where,dtype, or percentilemethod(linear only). Adding them will not likely be considered unless there is a strong use case, as they add complexity and maintenance burden. The main focus is on the core reduction logic and, more importantly, performance.
See the documentation for detailed API semantics, performance notes, axis behavior, and release wheels: https://ysbach.github.io/reducers/.
Maintainers: see RELEASING.md for CI, dependency updates, release rehearsals, trusted-publisher setup, and recovery.
Metadata
Release files for reducers 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| reducers-0.4.1.tar.gz | 104.7 kB | Without provenance | Details for reducers-0.4.1.tar.gz |
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| reducers-0.4.1-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details for reducers-0.4.1-cp310-abi3-win_amd64.whl |
| reducers-0.4.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details for reducers-0.4.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
| reducers-0.4.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details for reducers-0.4.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
| reducers-0.4.1-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details for reducers-0.4.1-cp310-abi3-macosx_11_0_arm64.whl |
| reducers-0.4.1-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details for reducers-0.4.1-cp310-abi3-macosx_10_12_x86_64.whl |
Total release size: 9.3 MB
Release files / reducers-0.4.1.tar.gz
| Download URL | reducers-0.4.1.tar.gz |
|---|---|
| Size | 104.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
99ba14e564e6865112af3c9abda0a1c4a3e9feb2c2bcea42ce6aafc09d6993d4
|
|
BLAKE2b-256 checksum How to use checksums |
0d2a059921ea4efc9bda947946d837da8bdd590ea340b0e04a28ff399735ff2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / reducers-0.4.1-cp310-abi3-win_amd64.whl
| Download URL | reducers-0.4.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 2.0 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
9aa58fbc14554f59048258116547f2fe233a9d2c950e83e823d47dcf03edefb2
|
|
BLAKE2b-256 checksum How to use checksums |
b31c98402b6ff9f1b5faa812e8cfffb8223025884d161c86deb49eaddf4734cf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / reducers-0.4.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | reducers-0.4.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.9 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
74f6b18bb9651aa5b293bc0ef8b5b4b3b93787001d0ae1c642e6895d0571870a
|
|
BLAKE2b-256 checksum How to use checksums |
0759b0d74d2925712985e1a3df328c766c7b190ad5318fb58e57bb409a758c4a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / reducers-0.4.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | reducers-0.4.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
59972a7900e83fe53cc7eb45a0b69999db622ec34475345aab1f9a30f095e405
|
|
BLAKE2b-256 checksum How to use checksums |
d027c44f4da96a2df024d20141df409852bb8dc5a6fa2d9d1087716b50dfa4dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / reducers-0.4.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | reducers-0.4.1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
a5040a60c86200bf9a718af9bb0a25b65c78c98623638774e459baa634b826fa
|
|
BLAKE2b-256 checksum How to use checksums |
93e7d9e429ca253ac50a8ae9fd231a87d141aa84224799fac57b3afdf3f1fd45
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / reducers-0.4.1-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | reducers-0.4.1-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
629955be35fc91b06a23d67cb4d15eacd4761a9622d4077662b575a1afa7d3bb
|
|
BLAKE2b-256 checksum How to use checksums |
96e1e34a7db17e2d34d0d4009f1d758ed299cf0da7251cffbd908c2c3ae13ea4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for reducers 0.4.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.