在Python中有效地找到scipy / numpy中非零的间隔?

时间:2010-04-12 01:25:30

标签: python arrays numpy scipy

假设我有一个python列表或一个python一维数组(以numpy表示)。假设有一个连续的元素段,我怎样才能找到这个列表或数组中非零段的起点和终点坐标(即索引)?例如,

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

nonzero_coords(a)应该返回[4,7]。为:

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

nonzero_coords(b)应该返回[0,2]。

感谢。

5 个答案:

答案 0 :(得分:4)

假设有一连串的非零元素......

x = nonzero(a)[0]
result = [x[0], x[-1]]

答案 1 :(得分:2)

这适用于我的多个洞

from numpy import *
def nonzero_intervals(value):
    lvalue = array(value)
    lvalue[0] = 0
    lvalue[-1] = 0
    a = diff((lvalue==0) * 1)
    intervals = zip( find(a == -1),find(a == 1))
    return intervals

答案 2 :(得分:1)

实际上,nonzero_coords(b)应该返回[0,3]。输入端可能出现多个孔吗?如果是,那该怎么办?天真的解决方案:扫描直到第一个非零el。然后扫描直到最后一个非零el。代码如下(抱歉没有测试):

a = [0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0]
start = 0
size = len(a) # 
while (start < size and a[start] != 0): start += 1
end = start
while (end < size and a[end] != 0): end += 1
return (start, end)

答案 3 :(得分:1)

nonzero_coords([0, 0, 0, 0, 1, 2, 3, 4])返回(4, 8)而不是(4, 7)的python索引会更加一致,因为[0, 0, 0, 0, 1, 2, 3, 4][4:8]会返回[1, 2, 3, 4]

这是一个计算非零间隔的函数。它处理多个间隔:

def nonzero_intervals(vec):
    '''
    Find islands of non-zeros in the vector vec
    '''
    if len(vec)==0:
        return []
    elif not isinstance(vec, np.ndarray):
        vec = np.array(vec)

    edges, = np.nonzero(np.diff((vec==0)*1))
    edge_vec = [edges+1]
    if vec[0] != 0:
        edge_vec.insert(0, [0])
    if vec[-1] != 0:
        edge_vec.append([len(vec)])
    edges = np.concatenate(edge_vec)
    return zip(edges[::2], edges[1::2])

如果您真的希望答案中包含岛上的结束索引,您只需将最后一行更改为:return zip(edges[::2], edges[1::2]-1)

试验:

a = [0, 0, 0, 0, 1, 2, 3, 4]
intervals = nonzero_intervals(a)
assert intervals == [(4, 8)]

a = [1, 2, 3, 4, 0, 0]
intervals = nonzero_intervals(a)
assert intervals == [(0, 4)]

a=[1, 2, 0, 0, 0, 3, 4, 0]
intervals = nonzero_intervals(a)
assert intervals == [(0, 2), (5, 7)]

a = [0, 4, 0, 6, 0, 6, 7, 0, 9]
intervals = nonzero_intervals(a)
assert intervals == [(1, 2), (3, 4), (5, 7), (8, 9)]

a = [1, 2, 3, 4]
intervals = nonzero_intervals(a)
assert intervals == [(0, 4)]

a = [0, 0, 0]
intervals = nonzero_intervals(a)
assert intervals == []

a = []
intervals = nonzero_intervals(a)
assert intervals == []

答案 4 :(得分:0)

如果你还是装了numpy,那就去找tom10的答案。

如果由于某种原因你想要的东西在没有加载numpy的情况下工作(不能想象为什么,说实话)那么我会建议这样的事情:

from itertools import groupby

def nonzero_coords(iterable):
  start = 0
  for iszero, sublist in groupby(iterable, lambda x:x==0):
    if iszero:
      start += len(list(sublist))
    else:
      return start, start+len(list(sublist))-1