从数组中提取单独的非零块

时间:2015-07-21 16:03:32

标签: python numpy extract

有一个像这样的数组:

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

Python中最快的方法是在列表中组织非零元素,其中每个元素包含连续非零值块的索引?

这里的结果将是一个包含许多数组的列表:

([0, 1, 2, 3], [9, 10, 11], [14, 15], [20, 21])

4 个答案:

答案 0 :(得分:8)

>>> L = [1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1]
>>> import itertools
>>> import operator
>>> [[i for i,value in it] for key,it in itertools.groupby(enumerate(L), key=operator.itemgetter(1)) if key != 0]

[[0, 1, 2, 3], [9, 10, 11], [14, 15], [20, 21]]

答案 1 :(得分:1)

查看scipy.ndimage.measurements.label

while (i < n){
        int a = LOAD_GLOBAL_I1(input, i);
        int b = LOAD_GLOBAL_I1(input, i + group_size);
        int s = LOAD_LOCAL_I1(shared, local_id);
        STORE_LOCAL_I1(shared, local_id, (a + b + s));
        i += local_stride;
}

#define ACCUM_LOCAL_I1(s, i, j) \ { \ int x = ((__local int*)(s))[(size_t)(i)]; \ int y = ((__local int*)(s))[(size_t)(j)]; \ ((__local int*)(s))[(size_t)(i)] = (x + y); \ } 包含您要求的内容。请注意,根据您的最终目标,import numpy as np from scipy.ndimage.measurements import label x = np.asarray([1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1]) labelled, numfeats = label(x) indices = [np.nonzero(labelled == k) for k in np.unique(labelled)[1:]] 也可能会为您提供有用的(额外)信息。

答案 2 :(得分:1)

Finding the consecutive zeros in a numpy array对我的回答进行了微不足道的更改,给出了函数find_runs

def find_runs(value, a):
    # Create an array that is 1 where a is `value`, and pad each end with an extra 0.
    isvalue = np.concatenate(([0], np.equal(a, value).view(np.int8), [0]))
    absdiff = np.abs(np.diff(isvalue))
    # Runs start and end where absdiff is 1.
    ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
    return ranges

例如,

In [43]: x
Out[43]: array([1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1])

In [44]: find_runs(1, x)
Out[44]: 
array([[ 0,  4],
       [ 9, 12],
       [14, 16],
       [20, 22]])

In [45]: [range(*run) for run in find_runs(1, x)]
Out[45]: [[0, 1, 2, 3], [9, 10, 11], [14, 15], [20, 21]]

如果示例中的值1不具代表性,并且您确实希望运行任何非零值(如问题文本所示),则可以将np.equal(a, value)更改为{ {1}}并适当地更改参数和注释。 E.g。

(a != 0)

例如,

def find_nonzero_runs(a):
    # Create an array that is 1 where a is nonzero, and pad each end with an extra 0.
    isnonzero = np.concatenate(([0], (np.asarray(a) != 0).view(np.int8), [0]))
    absdiff = np.abs(np.diff(isnonzero))
    # Runs start and end where absdiff is 1.
    ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
    return ranges

答案 3 :(得分:1)

一旦您知道非零的间隔,就可以使用np.split。长度和A中的相应索引。假设A作为输入数组,实现看起来像这样 -

# Append A on either sides with zeros
A_ext = np.diff(np.hstack(([0],A,[0])))

# Find interval of non-zeros lengths
interval_lens = np.where(A_ext==-1)[0] - np.where(A_ext==1)[0]

# Indices of non-zeros places in A
idx = np.arange(A.size)[A!=0]

# Finally split indices based on the interval lengths
out = np.split(idx,interval_lens.cumsum())[:-1]

示例输入,输出 -

In [53]: A
Out[53]: array([1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1])

In [54]: out
Out[54]: [array([0, 1, 2, 3]), array([ 9, 10, 11]), array([14, 15]), array([20, 21])]
相关问题