Suppose you have a numpy array and a list:
>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
[2, 1]])
>>> b = [
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
You can also use np.choose(idx, vals), where idx is an array of indices that indicate which value of vals should be put in their place. The indices must be 0-based, though. Also make sure that idx has an integer datatype. So you would only need to do:
np.choose(a.astype(np.int32) - 1, b)
I was unable to set the flags, or use a mask to modify the value. In the end I just made a copy of the array.
a2 = np.copy(a)
Read-only array in numpy can be made writable:
nArray.flags.writeable = True
This will then allow assignment operations like this one:
nArray[nArray == 10] = 9999 # replace all 10's with 9999's
The real problem was not assignment itself but the writable flag.
I found another solution with the numpy function place. (Documentation here)
Using it on your example:
>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
[2, 1]])
>>> np.place(a, a==1, 0)
>>> np.place(a, a==2, 10)
>>> a
array([[ 0, 10],
[10, 0]])
Well, I suppose what you need is
a[a==2] = 10 #replace all 2's with 10's