how do i change indexes in an array using numba

Viewed 240

I have a function in which I do some operations and want to speed it up with numba. In my code changing the values in an array with advanced indexing is not working. I think they do say that in the numba documents. But what is a workaround for like numpy.put()?

Here a short example what I want to do:

#example array
array([[ 0,  1,  2],
       [ 0,  2, -1],
       [ 0,  3, -1]])

changeing the values at given indexes with any method working in numba...to get: changed values at:[0,0], [1,2], [2,1]

#changed example array by given indexes with one given value (10)
array([[ 10,  1,  2],
       [ 0,  2, 10],
       [ 0,  10, -1]])

Here what I did in python, but not working with numba:

indexList is a Tuple, which works with numpy.take()

This is the working example python code and the values in the array change to 100.

x = np.zeros((151,151))
print(x.ndim)
indexList=np.array([[0,1,3],[0,1,2]])
indexList=tuple(indexList)

def change(xx,filter_list):
    xx[filter_list] = 100
    return xx

Z = change(x,indexList)

Now using @jit on the function:

@jit
def change(xx,filter_list):
    xx[filter_list] = 100
    return xx

Z = change(x,indexList)

Compilation is falling back to object mode WITH looplifting enabled because Function "change" failed type inference due to: No implementation of function Function() found for signature: setitem(array(float64, 2d, C), UniTuple(array(int32, 1d, C) x 2), Literalint)

This error comes up. So I need a workaround for this. numpy.put() is not supported by numba.

I would be greatful for any ideas.

Thankyou

2 Answers

If it's not a problem for your to keep the indexList as an array you can use it in conjunction with for loops in the change function to make it compatible with numba:

indexList = np.array([[0,1,3],[0,1,2]]).T

@njit()
def change(xx, filter_list):
    for y, x in filter_list:
        xx[y, x] = 100
    return xx
change(x, indexList)

Note that the indexList has to be transposed in order to have the y, x coordinates along the 1st axis. In other words, it has to have a shape of (n, 2) rather than (2, n) for the n points to be change. Effectively it's now a list of coordinates: [[0, 0],[1, 1],[3, 2]]

@mandulaj posted the way to go. Here a little different way I went before mandulaj gave his answer.

With this function I get a deprecation warning...so best way to go with @mandulaj and dont forget to transpose the indexList.

@jit
def change_arr(arr,idx,val): # change values in array by np index array to value
    for i,item in enumerate(idx):
        arr[item[0],item[1]]= val
    return arr

Related