0

I have a numpy 2d integer array:

a = numpy.array([[1, 1, 2, 2],
                 [0, 1, 2, 2],
                 [1, 3, 2, 3]])

I have a lookup table (list of tuples) with original values and new values:

lookup = [(0, 1), 
          (1, 0), 
          (2, 255)]

My task is to reclassify the original array based on the lookup table: all zeros in original array should become ones, all ones should become zeros, all values==2 should change to 255, other values should stay unchanged. The expected result is:

[[0, 0, 255, 255],
 [1, 0, 255, 255],
 [0, 3, 255, 3]]

I tried the following solution:

for row in lookup:
    original_value = row[0]
    new_value = row[1]
    a[a == original_value] = new_value

However, I did not get the desired result, the result of above operation is:

[[0, 0, 255, 255],
 [0, 0, 255, 255],
 [0, 3, 255, 3]]

notice result[1, 0] is 0 but it should be 1.

Is there method (other than a nested loop) to change values in the original array using my lookup table?

jirikadlec2
  • 1,256
  • 1
  • 23
  • 36
  • 1
    There is a similar question [here](https://stackoverflow.com/questions/3403973/fast-replacement-of-values-in-a-numpy-array), they use look-up table instead of dictionary – Brenlla Dec 11 '18 at 17:22
  • If the values in `a` are in the form 0, 1, 2... you can define `tovals = np.array(1,0,255,3)` and then simply `result = tovals[a]` – Brenlla Dec 11 '18 at 17:26
  • 1
    [This](https://stackoverflow.com/q/44928481) is almost the same question, only in that case missing mappings are filled with zero instead of left as they are. – jdehesa Dec 11 '18 at 17:29

3 Answers3

1

I think this works :

a = np.array([[1, 1, 2, 2],
             [0, 1, 2, 2],
             [1, 3, 2, 3]])
lookup = [(0, 1), 
          (1, 0), 
          (2, 255)]

result = (a == 0) + (a == 2) * 255 + (a != 1) * (a != 0) * (a != 2) * a

you have the following result:

 array([[  0,   0, 255, 255],
        [  1,   0, 255, 255],
        [  0,   3, 255,   3]])
ere
  • 56
  • 5
1

You can make a copy of your array 'a' that remains unmodified while in the 'for' loop:

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

lookup = [(0, 1), 
          (1, 0), 
          (2, 255)]

a_copy = np.copy(a)

for row in lookup:
    original_value = row[0]
    new_value = row[1]
    a[a_copy == original_value] = new_value
DavidPM
  • 455
  • 4
  • 10
1

You can do that like this:

import numpy as np

a = np.array([[1, 1, 2, 2],
              [0, 1, 2, 2],
              [1, 3, 2, 3]])
lookup = [(0, 1),
          (1, 0),
          (2, 255)]

lookup = np.asarray(lookup)
replacer = np.arange(a.max() + 1)
replacer[lookup[:, 0]] = lookup[:, 1]
result = replacer[a]
print(result)

Output:

[[  0   0 255 255]
 [  1   0 255 255]
 [  0   3 255   3]]
jdehesa
  • 58,456
  • 7
  • 77
  • 121