鉴于我有这个1d-numpy阵列。
a = np.array([True True True False False False False True True False True False False False False False False True True])
结果显示:
b = np.array([True True True False False False False False False False False False False False False False False True True])
为清晰起见,已编辑: 我如何(1)在1d数组的前导和尾随位置保持True值的“岛”,同时(2)将所有其他True值转换为False,用于不在前导或尾随“岛”中的真值1d阵列?
我已经尝试过明显的非效率答案,即通过它进行天真的迭代,但我不禁觉得有更好的解决方案。任何人都有更好的主意吗?
感谢您的阅读! :)
答案 0 :(得分:2)
方法#1
这是一种利用slicing
和numpy.maximum.accumulate
来检测岛屿起点和终点指数的方法 -
def fill_inner_islands(a):
acc = np.maximum.accumulate
start = a.argmax()
end = a.size-a[::-1].argmax()
a0 = ~a[start:end]
a[start:end] = ~(acc(a0) & acc(a0[::-1])[::-1])
样品运行 -
案例#1:
In [140]: a.astype(int)
Out[140]: array([1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1])
In [141]: fill_inner_islands(a)
In [142]: a.astype(int)
Out[142]: array([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1])
案例#2:
In [144]: a.astype(int)
Out[144]: array([1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0])
In [145]: fill_inner_islands(a)
In [146]: a.astype(int)
Out[146]: array([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0])
案例#3:
In [148]: a.astype(int)
Out[148]: array([1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0])
In [149]: fill_inner_islands(a)
In [150]: a.astype(int)
Out[150]: array([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0])
方法#2
更简单的方法 -
def fill_inner_islands_v2(a):
# Get stop and end indices of leading and trailing islands.
# We do this by using one-off shifted slices and looking for the fall
# in forward direction and fall in flipped direction
start = (a[1:] < a[:-1]).argmax()+1
end = a.size - 1 - (a[:-1][::-1] < a[1:][::-1]).argmax()
# Get the slice within those indices and assign as all False
if ~a[start:end].all(): # To handle all True in input array
a[start:end] = 0
答案 1 :(得分:1)
>>> a
array([ True, True, True, False, False, False, False, True, True,
False, True, False, False, False, False, False, False, True, True], dtype=bool)
假设数组以True开始和结束;使用np.diff找到True-False,False-True中断
>>> b = np.diff(a)
>>> b
array([False, False, True, False, False, False, True, False, True,
True, True, False, False, False, False, False, True, False], dtype=bool)
使用np.where
查找这些中断的索引>>> c = np.where(b)
>>> c = c[0]
>>> c
array([ 2, 6, 8, 9, 10, 16], dtype=int64)
>>>
>>> # c = b.nonzero()[0]
再次,假设数组以True开始和结束 - 您只关心第一个和最后一个中断
>>> x, y = c[0], c[-1]
>>> x, y
(2, 16)
>>>
在作业的左侧使用这些索引
>>> a[x+1:y] = False
>>> a
array([ True, True, True, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, True, True], dtype=bool)
>>>
答案 2 :(得分:0)
我为您提供了以下解决方案,它打算快速将False
设置为所有数据,然后恢复值。由于numpy数组的实例化,我不知道这是否比迭代每个值更快,但这是一种不同的方法,它不会改变a
的内容并且不会循环。
a = np.array([True, True, True, False, False, False, False, True, True, False, True, False, False, False, False, False, False, True, True])
b = np.array([False] * len(a))
b[0] = a[0]; b[-1] = a[-1]
根据您的反馈更新:
这很难看,但是没有循环,所以你可能会发现大量的True / False值很有趣。请注意,此处的数组不是一个numpy数组。
a = [True, True, True, False, False, True]
start = a.index(False)
a.reverse()
end = a.index(False) * -1
a.reverse()
result = a[:start] + [False] * (len(a) - (start + end * -1)) + a[end:]
答案 3 :(得分:0)
此问题的任何解决方案都涉及迭代。这是一个没有任何显式循环的东西:
b = a.tolist()
start = b.index(False)
end = b[::-1].index(False)
if end:
a[start : -end] = False
else:
a[start : ] = False