2

I have an array T. I am trying to find the number of values within a specified range through T1 but I am getting an error. I present the expected output.

T=np.array([4.7,5.1,2.9])
T1=np.flatnonzero(2<T<3,3<T<4,4<T<5)
print(T1)

The error is

in <module>
    T1=np.flatnonzero(2<T<3,3<T<4,4<T<5)

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

The expected output is

T1=[1,0,1]

3 Answers 3

2

You need to split the ranges to two and sum the results. You also don't need to use np.flatnonzero here, it's not really connected to what you are doing

T1 = ((2 < T) & (T < 3)).sum(), ((3 < T) & (T < 4)).sum(), ((4 < T) & (T < 5)).sum()
print(T1) # (1, 0, 1)
Sign up to request clarification or add additional context in comments.

2 Comments

Nice logic; .sum() is indeed more efficient than my .len() method :)
This works. How do I also print the actual values meeting this criterion? For instance, [2.9,None,4.7].
2

Why do you expect this to work?

  1. It breaks in 2<T<3. You can't use this kind of syntax in numpy. You should to replace 2<T<3 with (2<T) & (T<3) which is equivalent of np.logical_and. So you need the truth value of two boolean arrays (2<T) AND (T<3) element-wise as it said in docummentation.
  2. np.flatnonzero takes one single argument. If you want to plug in several conditions, use | (or np.logical_or) to get the truth value of two boolean arrays arr1 OR arr2 element-wise.
cond1 = (2<T) & (T<3) 
cond2 = (3<T) & (T<4) 
cond3 = (4<T) & (T<5) 

Number of conditions fulfilled for each value:

>>> np.sum([cond1, cond2, cond3], axis=0)
array([1, 0, 1])

Arrays of values that satisfies each condition:

>>> T[cond1], T[cond2], T[cond3]
(array([2.9]), array([], dtype=float64), array([4.7]))

Arrays of indices of values that satisfies each condition:

>>> np.flatnonzero(cond1), np.flatnonzero(cond2), np.flatnonzero(cond3)
(array([2], dtype=int64), array([], dtype=int64), array([0], dtype=int64))

2 Comments

Though it's related, this does not do what the OP wanted.
@Swifty Thanks for notice, fixed. It gets similar to your answer, I only use an approach from numpy side.
1
  • flatnonzero has nothing to do with what you want.
  • Furthermore, the error 'The truth value of an array with more than one element is ambiguous' comes from the double condition 2<T<3: you need to separate it into 2 conditions: (2<T) & (T<3).
  • T[(2<T) & (T<3)] will yield an array of the values of T respecting the conditions.

Thus, if you need to count the elements of T that are between 2 and 3, you can do:

len(T[(2 <T) & (T < 3)])

To obtain what you want, you could then do this:

Ranges = [(2,3),(3,4),(4,5)]
T1 = [len(T[(a < T) & (T < b)]) for a,b in Ranges]

print(T1)
# [1, 0, 1]

To print the actual values fitting the criteria, you can do:

T2 = [list(T[(a < T) & (T < b)]) for a,b in Ranges]

print(T2)
# [[2.9], [], [4.7]]

To get the corresponding indices, we finally have a use for flatnonzero:

T3 = [list(np.flatnonzero((a < T) & (T < b))) for a,b in Ranges]

print(T3)
# [[2], [], [0]]

1 Comment

This works. Is it also possible to print the corresponding indices? For example, corresponding to [[2.9],[],[4.7]], the indices should be [2,None,0].

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.