Skip to content
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

Faster rolling_min/rolling_max #1504

Closed
mrjbq7 opened this issue Jun 20, 2012 · 2 comments
Closed

Faster rolling_min/rolling_max #1504

mrjbq7 opened this issue Jun 20, 2012 · 2 comments
Milestone

Comments

@mrjbq7
Copy link

mrjbq7 commented Jun 20, 2012

See #50

Using a min-heap and max-heap to implement the rolling_min and rolling_max functions seems to be about 30% faster than the current implementation.

Something sort of like this:

from heapq import heappush, heapify
from numpy import empty, nan
cimport numpy as np

cdef extern from "math.h":
    bint isnan(double x)

cdef np.float64_t NaN = nan

def rolling_min(np.ndarray[np.float64_t] arg, int window):

    cdef Py_ssize_t N = len(arg)
    cdef np.ndarray[np.double_t] output = empty(N, dtype=float)
    cdef list min_heap = []

    for i from 0 <= i < N:
        x = arg[i]
        if isnan(x):
            min_heap = []
            output[i] = x
        else:
            heappush(min_heap, arg[i])
            if len(min_heap) < window:
                output[i] = NaN
            else:
                output[i] = min_heap[0]
                x = arg[i+1-window]
                min_heap.remove(x)
                heapify(min_heap)
    return output

def rolling_max(np.ndarray[np.float64_t] arg, int window):

    cdef Py_ssize_t N = len(arg)
    cdef np.ndarray[np.double_t] output = empty(N, dtype=float)
    cdef list min_heap = []

    for i from 0 <= i < N:
        x = arg[i]
        if isnan(x):
            min_heap = []
            output[i] = x
        else:
            heappush(min_heap, -arg[i])
            if len(min_heap) < window:
                output[i] = NaN
            else:
                output[i] = -min_heap[0]
                x = -arg[i+1-window]
                min_heap.remove(x)
                heapify(min_heap)
    return output
@wesm
Copy link
Member

wesm commented Jun 20, 2012

bottleneck (http://pypi.python.org/pypi/Bottleneck) has a very good rolling min/max implementation that's even better than using a heap, should just co-opt that code

@wesm wesm closed this as completed in 2dcae6e Jul 12, 2012
@wesm
Copy link
Member

wesm commented Jul 12, 2012

Done. Will be in 0.8.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants