在非零值之间交替填充 numpy 数组

Alternately fill numpy array between non-zero values

我有一个二进制 numpy 数组,大部分为零值,我想用给定值填充非零值之间的空白,但以另一种方式。 例如:

[0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0]

应该会导致

[0,0,1,1,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0]

[1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1,1,1]

想法是:从左到右扫描数组时,如果您没有这样做,则在下一个 1 之前用 1 填充 0 值。 我可以用这种方式迭代地做到这一点

A = np.array([0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0])
ones_index = np.where(A == 1)[0]
begins = ones_index[::2] # beginnings of filling section
ends = ones_index[1::2]  # ends of filling sections

from itertools import zip_longest

# fill those sections
for begin, end in zip_longest(begins, ends, fillvalue=len(A)):
    A[begin:end] = 1

但我正在寻找一个更有效的解决方案,也许使用 numpy 广播。有什么想法吗?

这个问题的一个很好的答案是,我们可以通过 np.logical_xor.accumulate(arr) | arr 产生第一个结果,通过 ~np.logical_xor.accumulate(arr) | arr 产生第二个结果。快速演示:

A = np.array([0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0])
print(np.logical_xor.accumulate(A) | A)
print(~np.logical_xor.accumulate(A) | A)

结果输出:

[0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0]
[1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0 1 1 1]
np.where(arr.cumsum() % 2 == 1, 1, arr)
# array([0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
#        0, 0, 1, 1, 1, 1, 0, 0])