簡體   English   中英

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

[英]efficiently finding the interval with non-zeros in scipy/numpy in Python?

假設我有一個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]。

謝謝。

假設有一個連續的非零元素......

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

這適用於我的多個洞

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

實際上,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)

對於nonzero_coords([0, 0, 0, 0, 1, 2, 3, 4])返回(4, 8)不是(4, 7) nonzero_coords([0, 0, 0, 0, 1, 2, 3, 4]) ,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 == []

如果你還是裝了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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM