https://github.com/marmarelis/rolling-quantiles

# Rolling Quantiles for NumPy

## Hyper-efficient and composable filters.

- Simple, clean, intuitive interface.
- Supports streaming data or bulk processing.
- Python 3 bindings for a lean library written in pure C.

### A Quick Tour

Let me give you but a superficial overview of this module's elegance.

```
import numpy as np
import rolling_quantiles as rq
pipe = rq.Pipeline( # rq.Pipeline is the only stateful object
# declare a cascade of filters by a sequence of immutable description objects
rq.LowPass(window=200, portion=100, subsample_rate=2),
# the above takes a median (100 out of 200) of the most recent 200 points
# and then spits out every other one
rq.HighPass(window=10, portion=3, subsample_rate=1))
# that subsampled rolling median is then fed into this filter that takes a
# 30% quantile on a window of size 10, and subtracts it from its raw input
# the pipeline exposes a set of read-only attributes that describe it
pipe.lag # = 60.0, the effective number of time units that the real-time output
# is delayed from the input
pipe.stride # = 2, how many inputs it takes to produce an output
# (>1 due to subsampling)
input = np.random.randn(1000)
output = pipe.feed(input) # the core, singular exposed method
# every other output will be a NaN to demarcate unready values
subsampled_output = output[1::pipe.stride]
```

That may be a lot to take in, so let me break it down for you:

`rq.Pipeline(description...)`

constructs a filter pipeline from one or more filter descriptions and initializes internal state.
`.feed(*)`

takes in a Python number or `np.array`

and its output is shaped likewise.
- The two filter types are
`rq.LowPass`

and `rq.HighPass`

that compute rolling quantiles and return them as is, and subtract them from the raw signal respectively. Compose them however you like!
`NaN`

s in the output purposefully indicate missing values, usually due to subsampling. If you pass a `NaN`

into a `LowPass`

filter, it will slowly deplete its reserve and continue to return valid quantiles until the window empties completely.

I also expose a convenience function `rq.medfilt(signal, window_size)`

at the top-level of the package to directly supplant `scipy.signal.medfilt`

.

That's it! I detailed the entire library. Don't let the size of its interface fool you!

## Installation

If you are running MacOS or Linux with Python 3.8+, execute the following: