我有一个这样的零的numpy数组。
a = np.array([3., 0., 2., 3., 0., 3., 3., 3., 0., 3., 3., 0., 3., 0., 0., 0., 0.,
3., 3., 0., 3., 3., 0., 3., 0., 3., 0., 0., 0., 3., 0., 3., 3., 0.,
3., 3., 0., 0., 3., 0., 0., 0., 3., 0., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 4., 3., 0., 3., 3., 3., 3., 3., 3., 3., 0.,
0., 0., 0., 3., 0., 0., 3., 0., 0., 0., 3., 3., 3., 3., 3., 3., 3.,
3., 0., 3., 3., 3., 3., 3., 0., 3., 3., 3., 3., 0., 0., 0., 3., 3.,
3., 0., 3., 3., 3., 5., 3., 3., 3., 3., 3., 3., 3., 0., 3., 0., 3.,
3., 0., 0., 0., 3., 3., 3., 3., 0., 3., 3., 3., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 0., 3., 3., 3., 3., 3., 3., 0., 3., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 0., 3., 0., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 0., 3., 3., 3., 3.,
3., 3., 3., 3., 3., 3., 3., 3., 0., 3., 3., 0., 0., 3., 0., 0., 3.,
0., 3., 3., 0., 3., 3., 0., 0., 3., 3., 3., 3., 3., 3., 3., 0., 3.,
3., 3., 3., 3.])
在某种情况下,我需要用以前的值替换零(向前填充)。如果两个非零数字之间的零个数小于或等于2,则需要向前填充零。
例如,
1)如果我考虑这三个数字3., 0., 2.
,则非零数字之间的零数字为1。这应该填充3。
2)如果我考虑3., 0., 0., 0., 0.,3., 3.
这些数字,则3之间的零数字大于2,因此它将保持不变。
我无法想象矢量化的方式,所以我只是寻找一种程序化的方式:
def ffill(arr, mx):
"""Forward fill 0 values in arr with a max of mx consecutive 0 values"""
first = None # first index of a sequence of 0 to fill
prev = None # previous value to use
for i, val in enumerate(arr):
if val == 0.: # process a null value
if prev is not None:
if first is None:
first = i
elif i - first >= mx: # to much consecutive 0: give up
prev = None
first = None
else:
if first is not None: # there was a sequence to fill
arr[first:i] = prev
first = None
这里是一种方法-
# https://stackoverflow.com/a/33893692/ @Divakar
def numpy_binary_closing(mask,W):
# Define kernel
K = np.ones(W)
# Perform dilation and threshold at 1
dil = np.convolve(mask,K)>=1
# Perform erosion on the dilated mask array and threshold at given threshold
dil_erd = np.convolve(dil,K)>= W
return dil_erd[W-1:-W+1]
def ffill_windowed(a, W):
mask = a!=0
mask_ext = numpy_binary_closing(mask,W)
p = mask_ext & ~mask
idx = np.maximum.accumulate(mask*np.arange(len(mask)))
out = a.copy()
out[p] = out[idx[p]]
return out
示例运行-
In [142]: a
Out[142]: array([2, 0, 3, 0, 0, 4, 0, 0, 0, 5, 0])
In [143]: ffill_windowed(a, W=2)
Out[143]: array([2, 2, 3, 0, 0, 4, 0, 0, 0, 5, 0])
In [144]: ffill_windowed(a, W=3)
Out[144]: array([2, 2, 3, 3, 3, 4, 0, 0, 0, 5, 0])
In [146]: ffill_windowed(a, W=4)
Out[146]: array([2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 0])