Подход № 1: Вот один с cumsum
-
def keep_lastNTrue_cumsum(a, n):
c = np.count_nonzero(a) # or a.sum()
a[c - a.cumsum() >= n] = 0
return a
Подход № 2: Еще два с argpartition
-
def keep_lastNTrue_argpartition1(a, n):
c = np.count_nonzero(a) # or a.sum()
a[np.sort(np.argpartition(a,-n)[-c:])[:-n]] = 0
return a
def keep_lastNTrue_argpartition2(a, n):
c = np.count_nonzero(a) # or a.sum()
p = np.argpartition(a,-n)[-a.sum():]
cn = c-n
idx = np.argpartition(p,cn)
a[p[idx[:cn]]] = 0
return a
Подход № 3: Другой с немного большим использованием маски -
def keep_lastNTrue_allmask(a, n):
c = a.sum()
set_mask = np.ones(c, dtype=bool)
set_mask[:-n] = False
a[a] = set_mask
return a
Примеры прогонов -
In [141]: boolean_array = np.array([False, False, True, True, True, False, False])
In [142]: keep_lastNTrue_cumsum(boolean_array, n=2)
Out[142]: array([False, False, False, True, True, False, False])
In [143]: boolean_array = np.array([False, False, True, True, True, False, False])
In [144]: keep_lastNTrue_argpartition1(boolean_array, n=2)
Out[144]: array([False, False, False, True, True, False, False])
In [145]: boolean_array = np.array([False, False, True, True, True, False, False])
In [146]: keep_lastNTrue_argpartition2(boolean_array, n=2)
Out[146]: array([False, False, False, True, True, False, False])