Number of values within a specific range in Python

Question:

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]
Asked By: user20032724

||

Answers:

  • 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]]
Answered By: Swifty

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)
Answered By: Guy

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))
Answered By: mathfux
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.