Search code examples
pythonperformancenumpyoptimizationindices

Fastest way to get indices of a np.array that meet my criteria


I am trying to find the fastest way to get the indices of the matrix elements that meet my criteria. I have a (7,7) np.array (named "board"), which contains int16 from 0 to 400. For example, I want to find the indices of the elements which are equal to 300.

I have tried many techniques and so far the fastest method is the np.where(board ==300)

The function I am trying to optimize:

def is_end(self, board):
    ind = np.where((board > 300) & (board - 300 < 100))
    try:
        victoriousPlayer = board[ind[0][0], ind[1][0]] % 100 // 10
        return victoriousPlayer
    except:
        return -1

Because I use this function tens of thousands of times I need it to run as fast as possible.


Solution

  • You don't need the indices in this case it seems, just a mask.

    ind = np.where((board > 300) & (board - 300 < 100))
    victoriousPlayer = board[ind[0][0], ind[1][0]] % 100 // 10
    

    is equivalent to

    victoriousPlayer = board[(board  > 300) & (board - 300 < 100)][0] % 100 // 10
    

    Timings:

    In [1]: import numpy as np                                                                                                    
    
    In [2]: board = np.random.randint(0,401, (7,7))                                                                               
    
    In [3]: %timeit ind = np.where((board > 300) & (board - 300 < 100));victoriousPlayer = board[ind[0][0], ind[1][0]] % 100 // 10
    6.77 µs ± 260 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
    In [4]: %timeit victoriousPlayer = board[(board  > 300) & (board - 300 < 100)][0] % 100 // 10                                 
    5.02 µs ± 26.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)