带条件的正向填充

问题描述 投票:2回答:1

我有一个这样的零的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,因此它将保持不变。

python numpy replace fill
1个回答
0
投票

我无法想象矢量化的方式,所以我只是寻找一种程序化的方式:

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

0
投票

这里是一种方法-

# 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])
© www.soinside.com 2019 - 2024. All rights reserved.