I have an ndarray
with n>1
dimensions. I have a boolean array ok0
corresponding to the rows I want to select, and another boolean array ok1
corresponding to the columns I want to select. I want to include all "pages". So I try Z[ok0, ok1, :]
, where ok0
is a 1-D boolean array with ok0.size == Z.shape[0]
, and ok1
is a boolean array with ok1.size == Z.shape[1]
. Is there a way to use these boolean arrays directly to index my nd-array?
A code fragment paints a thousand words.
In [50]: Z = arange(7*8*9).reshape(7, 8, 9)
In [51]: ok0 = Z.sum(1).sum(1)%10<3
In [52]: ok1 = Z.sum(0).sum(1)%10<5
In [53]: ok0.shape
Out[53]: (7,)
In [54]: ok1.shape
Out[54]: (8,)
In [55]: Z[ok0, :, :].shape
Out[55]: (3, 8, 9)
In [56]: Z[:, ok1, :].shape
Out[56]: (7, 4, 9)
In [57]: Z[ok0, ok1, :].shape
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-57-ebba5b9a19dd> in <module>()
----> 1 Z[ok0, ok1, :].shape
ValueError: shape mismatch: objects cannot be broadcast to a single shape
The desired effect can be achieved indirectly as follows:
In [58]: Z[ok0, :, :][:, ok1, :].shape
Out[58]: (3, 4, 9)
If I convert ok0
and ok1
from boolean arrays into integer arrays, I can use the solution provided in this answer to Selecting specific rows and columns from NumPy array:
In [88]: ok0i = ok0.nonzero()[0]
In [89]: ok1i = ok1.nonzero()[0]
In [90]: Z[ok0i[:, newaxis], ok1i, :].shape
Out[90]: (3, 4, 9)
However, this does not work with the original boolean arrays:
In [87]: Z[ok0[:, newaxis], ok1, :].shape
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-87-7e9fa28c47fa> in <module>()
----> 1 Z[ok0[:, newaxis], ok1, :].shape
ValueError: shape mismatch: objects cannot be broadcast to a single shape
Why does this not work — what's going wrong here? And (how) can I achieve the desired effect in one go, without repeating my full indexing (which could be potentially long) as I did in command 58?