[英]Python: Get last n Trues from Boolean array
I have a boolean array and a want to convert that to an array, where only the last_n_trues
True
values are still True
. 我有一个布尔数组,并且想要将其转换为仅
last_n_trues
True
值仍为True
的数组。 A simple example: 一个简单的例子:
>>> boolean_array = [False, False, True, True, True, False, False]
>>> last_n_trues = 2
>>> desired_output = [False, False, False, True, True, False, False]
My approach: 我的方法:
>>> import numpy as np
>>> idxs_of_trues = np.where(boolean_array)[0]
array([2, 3, 4], dtype=int64)
>>> idxs_of_trues_last_n = idxs_of_trues[-last_n_trues:]
array([3, 4], dtype=int64)
>>> [x in idxs_of_trues_last_n for x in range(0, len(boolean_array))]
[False, False, False, True, True, False, False]
Is there a faster way to do so? 有更快的方法吗? Especially the list comprehension seems pretty complicated to me...
特别是列表理解对我来说似乎很复杂。
You should just be able to simply use np.where
您应该只能够简单地使用
np.where
In [116]: x
Out[116]: array([False, False, True, True, True, False, False], dtype=bool)
In [117]: x[np.where(x)[0][:-2]] = False
In [118]: x
Out[118]: array([False, False, False, True, True, False, False], dtype=bool)
This just replaces all True
that aren't the last 2 with False
这只是用
False
代替不是最后2个的所有True
This will only work if x
is a np.array
, so verify that before you try this. 仅当
x
是np.array
,此方法才有效,因此在尝试此操作之前请先进行验证。
Approach #1 : Here's one with cumsum
- 方法#1:这是一个带有
cumsum
-
def keep_lastNTrue_cumsum(a, n):
c = np.count_nonzero(a) # or a.sum()
a[c - a.cumsum() >= n] = 0
return a
Approach #2 : Two more with argpartition
- 方法2:使用
argpartition
另外两个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
Approach #3 : Another with a bit more of mask usage - 方法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
Sample runs - 样品运行-
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])
The fastest way without libraries is going to be to clone the list and iterate through it in reverse: 没有库的最快方法是克隆列表,然后反向遍历它:
def foo(bools, last_n_trues):
result = bools[:]
count = 0
for i in range(len(bools) - 1, -1, -1):
if count < last_n_trues:
if result[i]:
count += 1
else:
result[i] = False
return result
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.