0

Suppose there is a sorted array a and a matrix b

a = np.array([11,30,60,70])

b = np.array([[11, 2, 30, 4],
              [30, 60, 70, 5],
              [1, 2, 3, 4]]
            )

I could get the results like

 results = np.array([[0, 2, 1, 4],
                     [1, 2, 3, 5],
                     [1, 2, 3, 4]]
                    )

It means searching each element from array a in matrix b and replace the founded one with the index in array a.

I know it is a bit complex, I have done it in a loop

def set_values_found_to_index(matrix_original, values_to_find):

"""Set value found to index."""

for index, elem in enumerate(values_to_find):

    matrix_original[np.where(

            values_to_find == values_to_find[index]

    )] = index

return matrix_original

My question is there any chance to do it without a loop?

Updated: @NilsWerner code works perfectly regarding the above question, because there are still ambiguous questions about the apple and pear mix, so I update the question:

a = np.array([11,30,60,70])

b = np.array(
             [[11, 2, 30],
              [30, 60, 70],
              [20, 30, 50],
              [11, 30, 60],
              [30, 11, 70],
              [70, 11, 60],
              [1, 2, 3]]
             )
results = np.array(
                   [[1,2,3],
                    [0,1,2],
                    [1,0,3],
                    [3,0,2]]
                   )

It means based on the above question, the apple and pear mix problem can be solved by remove the lines which contain the elements either smaller than a.min(), bigger than a.max() or not in a.

  • Related: [Fast replacement of values in a numpy array](https://stackoverflow.com/q/3403973/846892) – Ashwini Chaudhary May 10 '17 at 14:55
  • In `results` if you find the element you put the index otherwise you just keep the value in the matrix. You are mixing apples and pears!! The 2 in position(0,1) is the original value of the matrix, the 2 in (1,2) is the index of the element 70 in the array. Are you sure this is what you want?? –  May 10 '17 at 15:10
  • @SembeiNorimaki That is what I want, but I just noticed there is a bug about my question, thank you for the cue. Just corrected it. – user3922048 May 11 '17 at 09:18

2 Answers2

0
translation = dict(map(reversed, enumerate(a)))
translate = np.vectorize(lambda i: translation.get(i, i))
results = translate(b)

translation forms a dictionary mapping elements in a to their index. translate is a vectorize object that applies a function to every element in the object it is called with. The function in this case tries to get the value mapped to in translation, returning the original if not found.

Artyer
  • 31,034
  • 3
  • 47
  • 75
  • Thanks for reply, is there any chance to git rid of the loop? Because I got a big var a and b. – user3922048 May 11 '17 at 09:19
  • @user3922048 I removed the for loop in the dict comprehension, but note that it still loops over `a` and `b`, just down at C, so it should be faster for big `a` and `b`. – Artyer May 11 '17 at 09:25
0

For a fully vectorized solution you can use a combination of np.in1d and np.searchsorted:

np.searchsorted(a, b[~np.any(~np.in1d(b, a).reshape(b.shape), axis=1), :])
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
  • Thanks bro, it works for me. I will test it a bit more. – user3922048 May 11 '17 at 12:34
  • thank you first of all, well it solved the above question. But as @SembeiNorimaki mentioned, there will be a problem mixing the apples and pears. It means if a and b are very large, the results will be ambiguous. For example, the results[1,1] is the same as the results[0,1], which is not from the calculation. So what I want to improve is trying to remove the lines containing the elements between the elements in a. I have updated the question. – user3922048 May 12 '17 at 15:39
  • Sorry this is my first post. It won't happen next time. And It works!!! Thanks a lot bro. Is there any chance to talk with you personally? – user3922048 May 15 '17 at 09:12
  • Accepted. :) Thanks again! So could I talk with you by mail or others please? – user3922048 May 15 '17 at 10:01