pythonnumpyvector

Get last non-zero index in a vector


I have a 1D NumPy array, and I want to find the index of the last non-zero element. The vector consists only of 1s and 0s, not sure if this is relevant information.

For example:

import numpy as np

vec = np.array([0, 1, 1, 0, 0, 1, 0, 0])

In this case, the result should be 5 because vec[5] == 1 is the last non-zero value.

What is the most efficient way to do this using NumPy?

I am forced to use Python, but this will run a few million times with arrays that are quite a bit larger than the example and I need this to be as performant as possible. Any little edge helps.

Here are two approaches I currently have. One using standard python loops, the other one trying to leverage what NumPy gives me. I feel like there might be some elegant way of making this even more performant, but I am constrained by only having an Economics degree.

def last_nonzero_index(vec):
    for i in range(len(vec) - 1, -1, -1):
        if vec[i] != 0:
            return i
    return None
def last_nonzero_index(vec):
    rev_idx = np.flatnonzero(vec[::-1])
    return len(vec) - 1 - rev_idx[0] if rev_idx.size else None

Right now the native python loop does beat everything else.


Solution

  • Use Numba JIT compilation. It's significantly faster than any NumPy-based approach.

    from numba import njit
    import numpy as np
    
    @njit
    def find_last_nonzero(vec):
        """Finds the last non-zero element's index in a vector"""
        for i in range(len(vec) - 1, -1, -1):
            if vec[i] != 0:
                return i
        return -1 
    

    Usage

    vec = np.array([0, 1, 1, 0, 0, 1, 0, 0])
    result = find_last_nonzero(vec)
    print(result)
    

    enter image description here