Опция, использующая numpy
, заключается в том, чтобы начать с добавления строк в mask
:
take = boolarr.sum(axis=1)
#array([2, 1, 3])
Затем замаскировать массив так, как вы:
x = arr[boolarr]
#array([1, 2, 1, 1, 2, 3])
И использоватьnp.split
для разбиения плоского массива в соответствии с np.cumsum
из take
(так как функция ожидает индексы, где разбивать массив):
np.split(x, np.cumsum(take)[:-1])
[array([1, 2]), array([1]), array([1, 2, 3])]
Общее решение
def mask_nd(x, m):
'''
Mask a 2D array and preserve the
dimension on the resulting array
----------
x: np.array
2D array on which to apply a mask
m: np.array
2D boolean mask
Returns
-------
List of arrays. Each array contains the
elements from the rows in x once masked.
If no elements in a row are selected the
corresponding array will be empty
'''
take = m.sum(axis=1)
return np.split(x[m], np.cumsum(take)[:-1])
Примеры
Давайте рассмотрим несколько примеров:
arr = np.array([[1,2,4],
[2,1,1],
[1,2,3]])
boolarr = np.array([[True, True, False],
[False, False, False],
[True, True,True]])
mask_nd(arr, boolarr)
# [array([1, 2]), array([], dtype=int32), array([1, 2, 3])]
Или для следующих массивов:
arr = np.array([[1,2],
[2,1]])
boolarr = np.array([[True, True],
[True, False]])
mask_nd(arr, boolarr)
# [array([1, 2]), array([2])]