2

Say I have a numpy array as follows:

arr = np.array([[[1, 7], [5, 1]], [[5, 7], [6, 7]]])

where each of the innermost sub-arrays is an element. So for example; [1, 7] and [5, 1] are both considered elements.

... and I would like to find all the elements which satisfy: [<=5, >=7]. So, a truthy result array for the above example would look as follows:

arr_truthy = [[True, False], [True, False]]

... as for one of the bottom elements in arr the first value is <=5 and the second is >=7.

I can solve this easily by iterating over each of the axes in arr:

    for x in range(arr.shape[0]):
        for y in range(arr.shape[1]):
            # test values, report if true.

.. but this method is slow and I'm hoping there's a more numpy way to do it. I've tried np.where but I can't work out how to do the multi sub-element conditional.

I'm effectively trying to test an independent conditional on each number in the elements.

Can anyone point me in the right direction?

0

3 Answers 3

3

I would do it like this. Initialize output to the same shape. Then just do the comparison on those elements.

out = np.full(arr.shape,False)
out[:,:,0] = arr[:,:,0] >= 5
out[:,:,1] = arr[:,:,1] >= 8

Output:

array([[[False, False],
        [ True, False]],

       [[ True,  True],
        [ True, False]]])

EDIT: After our edit I think you just need a final np.all along the last axis:

np.all(out, axis=-1)

Returns:

array([[False, False],
       [ True, False]])
Sign up to request clarification or add additional context in comments.

1 Comment

Apologies.. I just updated my question a touch.. but your logic should still hold. I'll test it out.
3

Are you looking for

(arr[:,:,0] <= 5) & (arr[:,:,1] >= 7)

? You can perform broadcasted comparison.

Output:

array([[True, False],
       [True, False]])

3 Comments

While your answer is correct, you've made me aware of an issue with my question. I'll edit it to clarify.
@desiguel response updated, can you check if this works?
Nice. I'll test it out.
1

In your example the second pair ([5, 1]) matches your rule (the first value is >=5 and the second is <=7), but in the result(arr_truthy) its value is False. My code works if this was a mistake, otherwise please clarify the condition.

arr = np.array([[[1, 7], [5, 1]], [[5, 6], [6, 7]], [[1, 9], [9, 1]]])

# Create True/False arrays for the first/second element of the input
first = np.zeros_like(arr, dtype=bool)
first = first.flatten()
first[::2] = 1
first = first.reshape(arr.shape)
second = np.invert(first)

# The actual logic:
out = np.logical_or(np.where(arr >= 5, first, False), np.where(arr <= 7, second, False))
# Both the condition for the first and for the second element of each par has to be meet
out = out.all(axis=-1)

1 Comment

Nice. Thanks for helping but the other two answers look like they do something similar to yours more concisely by using array slice shorthand. Pretty cool actually.. today I learned how to slice arrays!

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.