2

I need help) I have NumPy array:

False False False False
False True  True  False
True  True  True  True
False True  True  False
False False False False

How can I get this (take first and last rows, that contains True, and set all of them elements to False)?

False False False False
False False False  False
True  True  True  True
False False False  False
False False False False

2 Answers 2

4
arr[arr.any(axis=1).nonzero()[0][[0,-1]]] = False

How it works:

In [19]: arr

Out[19]: 
array([[False, False, False, False],
       [False,  True,  True, False],
       [ True,  True,  True,  True],
       [False,  True,  True, False],
       [False, False, False, False]], dtype=bool)

arr.any(axis=1) finds which rows contains a True value:

In [20]: arr.any(axis=1)
Out[20]: array([False,  True,  True,  True, False], dtype=bool)

nonzero returns a tuple (one item for each axis) of indices of the True rows:

In [21]: arr.any(axis=1).nonzero()
Out[21]: (array([1, 2, 3]),)

We can use indexing to find the index of the first and last row containing a True value:

In [22]: arr.any(axis=1).nonzero()[0][[0,-1]]
Out[22]: array([1, 3])

And finally, we can set those rows to False with

In [23]: arr[arr.any(axis=1).nonzero()[0][[0,-1]]] = False

In [24]: arr
Out[24]: 
array([[False, False, False, False],
       [False, False, False, False],
       [ True,  True,  True,  True],
       [False, False, False, False],
       [False, False, False, False]], dtype=bool)
Sign up to request clarification or add additional context in comments.

2 Comments

@erthalion Does this answer the question generally? I interpret the question as: if a row has both True and False values, then set all values to False. Not just the first and last rows that fit that condition. If more than two rows fit that condition, this answer misses some. I would just do: arr[~a.all(1)] = False.
@askewchan: Yes, in the my question I thought about the first/last rows only.
1

In case you meant "first and last" only in reference to the particular example ...

If every row that contains both True and False values should be set to False, then you shouldn't restrict to the "first and last" of these rows, and the solution is much easier. Using the fact that ~a.all(1) will tell you which rows are not all True, you can set those rows to False with:

arr[~arr.all(1)] = False

or, to avoid redundantly setting rows of entirely False to False, use exclusive or, ^:

arr[arr.any(1) ^ arr.all(1)] = False

which will be faster in some circumstances.

Comments

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.