Replace Values of a Numpy Index Array With Values of a List

Replace values of a numpy index array with values of a list

Instead of replacing the values one by one, it is possible to remap the entire array like this:

import numpy as np
a = np.array([1,2,2,1]).reshape(2,2)
# palette must be given in sorted order
palette = [1, 2]
# key gives the new values you wish palette to be mapped to.
key = np.array([0, 10])
index = np.digitize(a.ravel(), palette, right=True)
print(key[index].reshape(a.shape))

yields

[[ 0 10]
[10 0]]

Credit for the above idea goes to @JoshAdel. It is significantly faster than my original answer:

import numpy as np
import random
palette = np.arange(8)
key = palette**2
a = np.array([random.choice(palette) for i in range(514*504)]).reshape(514,504)

def using_unique():
palette, index = np.unique(a, return_inverse=True)
return key[index].reshape(a.shape)

def using_digitize():
index = np.digitize(a.ravel(), palette, right=True)
return key[index].reshape(a.shape)

if __name__ == '__main__':
assert np.allclose(using_unique(), using_digitize())

I benchmarked the two versions this way:

In [107]: %timeit using_unique()
10 loops, best of 3: 35.6 ms per loop
In [112]: %timeit using_digitize()
100 loops, best of 3: 5.14 ms per loop

Getting and replace values from numpy array based on list of index

Use np.r_:

larr = np.array([0, 1, 2, 8, 4, 9, 1, 2])
larr[np.r_[3, 5]]

Output

array([8, 9])

As @MadPhysicist suggest, using larr[np.array([3, 5])] will work also, and is faster.

How replace values from one numpy array by other array with indices

Try advanced indexing:

x[np.arange(len(x)), a] = y

I found also this tutorial easier for me than official documentation.

How can I replace values in a Python NumPy array with the index of those values found in another array?

This is posted as an answer only because it is too long for a comment. It supports orlp's solution posted above.
Numpy's vectorize avoids an explicit loop, but it is clearly not the best approach.
Note that Numpy's searchsorted can only be applied as shown when b is sorted.

import timeit
import numpy as np

a = np.random.randint(1,100,(1000,1000))
b = np.arange(0,1000,1)

def o1():
lo = min(a.min(), b.min())
hi = max(a.max(), b.max())
lut = np.zeros(hi - lo + 1, dtype=np.int64)
lut[b - lo] = np.arange(len(b))
a2 = lut[a - lo]
return a2

def o2():
a2 = a.copy()
fu = np.vectorize(lambda i: np.place(a2, a2==b[i], i))
fu(np.arange(0,len(b),1))

print(timeit.timeit("np.searchsorted(b, a)", globals=globals(), number=2))
print(timeit.timeit("o1()", globals=globals(), number=2))
print(timeit.timeit("o2()", globals=globals(), number=2))

prints

0.061956800000189105
0.012765400000716909
2.220097600000372

Is there way to replace an element in a numpy array with its index

You can use numpy.where:

w = np.where(a%2 == 0) #(array([0, 0, 1, 1]), array([0, 2, 0, 2]))
a[w] = w[0]

It returns the indices where the condition is True separated by axis, in this case, rows and columns.


A pretty similar approach would be using numpy.nonzero:

w = np.nonzero(a%2 == 0)
a[w] = w[0]

Note: following the documentation, nonzero should be preferred over where in this case.

Replace values of an array based on a vector of indices

You can just index your value array with the indices array as they are integers (required for indexing):

vals[ind]

which produces:

array([0.2, 0.2, 0.3, 0.2])

as desired.



Related Topics



Leave a reply



Submit