1

I have numpy array, and I do want to map the ranges of the array values into specific values:

import numpy as np

array = [
[328, 124, 146, 117, 147, 109, 139, 100, 140, 98, 128, 101, 121, 95, 111, 89, 114, 82, 106, 77, 97, 71, 273], 
[132, 121, 121, 117, 114, 110, 99, 163, 89, 81, 83, 81, 91, 91, 89, 144, 89, 81, 81, 75, 69, 68, 68], 
[164, 114, 117, 110, 105, 105, 97, 91, 142, 80, 131, 77, 122, 81, 108, 74, 77, 75, 69, 71, 68, 63, 87], 
[121, 116, 110, 103, 104, 99, 90, 84, 77, 137, 77, 125, 99, 128, 79, 73, 69, 71, 68, 70, 60, 53, 64], 
[151, 100, 103, 99, 379, 88, 264, 78, 135, 77, 121, 97, 113, 75, 100, 62, 232, 65, 350, 54, 56, 50, 75], 
[101, 93, 121, 90, 84, 92, 86, 78, 74, 113, 66, 115, 72, 100, 63, 67, 60, 57, 57, 47, 47, 44, 43], 
[146, 89, 116, 86, 87, 85, 79, 73, 101, 59, 98, 63, 107, 64, 62, 56, 56, 52, 48, 50, 46, 38, 68], 
[89, 113, 108, 83, 82, 78, 74, 125, 69, 67, 57, 65, 67, 56, 58, 105, 49, 52, 69, 59, 63, 34, 43], 
[127, 87, 78, 79, 105, 74, 163, 64, 61, 61, 56, 235, 61, 48, 51, 43, 134, 40, 63, 28, 31, 26, 55], 
[76, 79, 75, 70, 72, 69, 62, 58, 53, 52, 49, 50, 53, 43, 39, 37, 41, 36, 31, 29, 26, 18, 17], 
[274, 73, 96, 71, 92, 64, 87, 57, 82, 53, 81, 30, 73, 41, 66, 37, 52, 31, 49, 22, 50, 15, 211]]

array = np.array(array)

def mapVal(val, table = [140, 195, 250, 350, 450]):
    """
    Function: mapVal, to quantify depth values manually.
    ---
    Parameters:
    @param: val, nd-array.
    @param: table, list, mapping table.

    ---
    @return: None.
    """
    
    val[val <= table[0]]  = 0
    val[val >  table[0] & val <=  table[1]]  = 1
    val[val >  table[1] & val <=  table[2]]  = 2
    val[val >  table[2] & val <=  table[3]]  = 3
    val[val >  table[3] & val <=  table[4]]  = 4
    val[val >  table[4]]  = 5

But I'm getting this Error:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I'm awar that I can use inefficient loops, but I do like to ask if there is a better solution, thanks in advance.

7
  • How are you calling mapVal? Commented Apr 20, 2022 at 12:13
  • @EmiOB like this: mapVal(array) Commented Apr 20, 2022 at 12:15
  • 2
    You need to add parenthesis - e.g. val[(val > table[0]) & (val <= table[1])], since the & is a bitwise operation and takes priority by default. This should address your ValueError Commented Apr 20, 2022 at 12:16
  • 1
    Does this fully answer your question? or are you still in search for a "more efficient" way? Commented Apr 20, 2022 at 12:18
  • 1
    You method is already decent. Perhaps use a for-loop for conciseness. If you really must find a more efficient way, you can use np.digitize(array, table) in your case. Commented Apr 20, 2022 at 12:37

2 Answers 2

3

As mentioned in the comments, first solve your ValueError by using parenthesis around your conditional checks to avoid having the bit-wise and operator & be evaluated first, which is the default behaviour.

For example:

val[(val > table[0]) & (val <= table[1])]

Next, for your search for a more efficient method, you can use the built-in np.digitize function to help you do what you're doing:

np.digitize(array, table)

Sign up to request clarification or add additional context in comments.

4 Comments

np.digitize(array, table) doesn't yield the same output of my manual function mapVal.
they should be the same. perhaps ensure that you are passing a new instance of the array with the original values for verification since your function modifies the input array.
For np.digitize to work correctly, the table should contain all the values and not just some of them. Otherwise some values are not replaced. Thus, the map should be corrected first. On solution is to use np.searchsorted to generate it. Boundaries also still need to be checked. This approach should be pretty fast.
You are right. that's oversight on my part
2

There is a much simpler and much faster way to do what you want:

table = np.array([140, 195, 250, 350, 450])
result = np.searchsorted(table, array)

This assume that the table is sorted though which is the case here. If it is not, then you can use np.argsort to reorder the table and np.digitize to remap the values.

3 Comments

thanks for your kind suggestion, I have compared the output of of my manual function mapVal, and it looks different from the output of your solution, the objective of mapVal function is to generate a discrete output with values [1, 2, 3, 4, 5] that corresponds to pre-defined ranges.
This is surprising. I checked the results and it was fine on my machine with your example. Note that your function mutate the input array so you certainly need to reload the values between the use of your function and the proposed code. Alternatively, you can .copy() the input array so to be safe.
you are right, thanks for your kind explanation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.