如何标记和分组数组中的唯一要素

时间:2017-12-21 08:41:57

标签: python arrays numpy scipy label

这里是python的新手。我有以下示例数组:

a = [0,0,1,1,0,0,1,1,2,2,3,3,4,4,0,0]

我想根据连续出现的唯一值来标记和切片数组,即连续出现的相同元素将被分配相同的标签,否则将被分配不同的标签。这样做是为了完成而不需要zeros分隔来分配不同的标签,就像scipy.ndimage.label之类的那样。

因此,scipy.ndimage.label的输出不是我所期望的:

lbl = label(a)
lbl = [0,0,1,1,0,0,2,2,2,2,2,2,2,2,0,0]

如您所见,它将[...,1,1,2,2,3,3,4,4,...]的整个序列组合为一个标签,而不是四个唯一标签。而我想要的是这样的:

lbl = [0,0,1,1,0,0,2,2,3,3,4,4,5,5,0,0]

我是否遗漏了该功能的某些内容,还是有其他方法可以做到这一点?

1 个答案:

答案 0 :(得分:0)

方法#1:这是一种方法 -

def label_based_on_shifts(a):
    # Detect starts of each label(element is non-zero and is different 
    # from the previous element)
    mask = np.r_[a[0]!=0,(a[1:] != a[:-1]) & (a[1:] !=0)]

    # Setup id array, which when cumulatively summed would lead us to
    # labelled islands
    out = mask.astype(np.uint64).cumsum()    

    # Set the islands that are zeros in input array to be zeros in o/p too
    out[a==0] = 0
    return out

示例运行 -

In [53]: a
Out[53]: array([0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0])

In [54]: label_based_on_shifts(a)
Out[54]: array([0, 0, 1, 1, 0, 0, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0])

方法#2:另一个用np.cumsum替换np.repeat -

def label_based_on_shifts_v2(a):
    mask = np.r_[True,(a[1:] != a[:-1]),True]
    idx = np.flatnonzero(mask)

    valid_idx_mask = a[idx[:-1]]!=0
    starts = idx[:-1][valid_idx_mask]
    stops = idx[1:][valid_idx_mask]
    lens = stops-starts

    out = np.zeros(len(a), dtype=int)
    out[a!=0] = np.repeat(np.arange(1,len(starts)+1), lens)
    return out