【问题标题】:change gaps in numpy array according to gap size根据间隙大小更改 numpy 数组中的间隙
【发布时间】:2020-10-29 00:34:43
【问题描述】:

我需要过滤掉介于零之间的短非零系列。比如这个数组:

t = np.array([1, 3, 1, 0, 0, 1, 8, 3, 0, 8, 2, 4, 7, 0,0,4,1])

应该变成:

array([1, 3, 1, 0, 0, 0, 0, 0, 0, 8, 2, 4, 7, 0, 0, 4, 1])

我找到了非零序列的第一个索引,并计算了它们之间的非零数。我写了以下内容,它有效,但看起来很糟糕。我尝试了工作人员,但出现错误。 如何用pythonicly重写它?

minseq = 4  # length of minimal non zero seq
p = np.where(fhr>0, 1, 0).astype(int)
s = np.array([1]+ list(np.diff(p)))
sind = np.where(s==1)[0][1:]
print(sind)
    
for i in range(len(sind) - 1):
    s1 = sind[i]
    e1 = sind[i+1]
    
    subfhr = np.where(fhr[s1:e1] > 0, 1, 0).sum()
    
    if (subfhr < minseq):
        
        print(s1, e1, subfhr)
        fhr[s1:e1] = 0

出来:

[ 5  9 15]
5 9 3
array([1, 3, 1, 0, 0, 0, 0, 0, 0, 8, 2, 4, 7, 0, 0, 4, 1])

【问题讨论】:

  • 只是好奇,为什么8 2 4 7 系列不归零?
  • @QuangHoang 必须是窗口参数,因为它会删除 1, 8, 3,但不会删除 8 2 4 7
  • @QuangHoang 8,2,4,7 长度为 4,1,8,3 长度为 3。我会更正问题

标签: python numpy conditional-statements sequence


【解决方案1】:

您可以使用基于图像处理的binary_closing -

from scipy.ndimage.morphology import binary_closing

def remove_small_nnz(a, W):
    K = np.ones(W, dtype=int)
    m = a==0
    p = binary_closing(m,K)
    a[~m & p] = 0
    return a

示例运行 -

In [97]: a
Out[97]: array([1, 3, 1, 0, 0, 1, 8, 3, 0, 8, 2, 4, 7, 0, 0, 4, 1])

In [98]: remove_small_nnz(a, W=3)
Out[98]: array([1, 3, 1, 0, 0, 1, 8, 3, 0, 8, 2, 4, 7, 0, 0, 4, 1])

In [99]: remove_small_nnz(a, W=4)
Out[99]: array([1, 3, 1, 0, 0, 0, 0, 0, 0, 8, 2, 4, 7, 0, 0, 4, 1])

In [100]: remove_small_nnz(a, W=5)
Out[100]: array([1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1])

【讨论】:

    【解决方案2】:

    由于您只是在寻找非零值,因此您可以将数组转换为布尔值,并根据您的需要寻找连续存在多个 True 序列的点。

    import numpy as np
    
    def orig(fhr, minseq):
        p = np.where(fhr>0, 1, 0).astype(int)
        s = np.array([1]+ list(np.diff(p)))
        sind = np.where(s==1)[0][1:]
        for i in range(len(sind) - 1):
            s1 = sind[i]
            e1 = sind[i+1]
            subfhr = np.where(fhr[s1:e1] > 0, 1, 0).sum()
    
            if (subfhr < minseq):
    
                fhr[s1:e1] = 0
        return fhr
    
    def update(fhr, minseq):
        # convert the sequence to boolean
        nonzero = fhr.astype(bool)
        # stack the boolean array with lagged copies of itself
        seqs = np.stack([nonzero[i:-minseq+i] for i in range(minseq)],
                        axis=1)
        # find the spots where the sequence is long enough
        inseq = np.r_[np.zeros(minseq, np.bool), seqs.sum(axis=1) == minseq]
        # the start and end of the series is are assumed to be included in result
        inseq[minseq] = True
        inseq[-1] = True
        
        # make sure that the full sequence is included. 
        # There may be a way to vectorize this further
        for ind in np.where(inseq)[0]:
            inseq[ind-minseq:ind] = True
        # Apply the inseq array as a mask
        return inseq * fhr
    
    
    fhr = np.array([1, 3, 1, 0, 0, 1, 8, 3, 0, 8, 2, 4, 7, 0,0,4,1])
    minseq = 4 
    
    print(np.all(orig(fhr, minseq) == update(fhr, minseq)))
    # True
    

    【讨论】:

      猜你喜欢
      • 2015-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-17
      • 2022-12-12
      相关资源
      最近更新 更多