2013-07-29 38 views
2

我有NumPy數組表示一個序列的分段。 B是感興趣片段的開始,I其延續,O在任何片段之外。例如,下面的陣列中,有感興趣的三個部分:數組的最長前綴等於一個值

>>> y 
array(['B', 'I', 'I', 'O', 'B', 'I', 'O', 'O', 'B', 'O'], 
     dtype='|S1') 

我能找到段與np.where(y == "B")[0]容易啓動。但是現在我試圖找出段的長度,即最長前綴的長度等於I。我可以這樣做使用itertools.takewhile

>>> from itertools import takewhile 
>>> lengths = [1 + sum(1 for _ in takewhile(lambda x: x == "I", y[start + 1:])) 
...   for start in np.where(y == "B")[0]] 
>>> lengths 
[3, 2, 1] 

其中,要誠實,工作正常,但有一個量化的方式來實現這一目標?

+0

出於好奇,是否有所有numpy方法在某處擴展的列表? – Daniel

+0

@Ophion:不是我所知道的。大多數只是線性時間,但搜索和排序顯然不可能。 –

回答

1

的細分'B'開始其次是以外的其他內容,或者通過序列的結尾:

ends = np.where(((y == 'B') | (y == 'I')) & np.r_[y[1:] != 'I', len(y)])[0] 

這給段長度:

(ends - starts) + 1 
array([3, 2, 1]) 

編輯:這裏有一個簡單的方法:在結尾處一個虛構B,然後取(真實或虛構)B s的位置的差異,不包括O s:

np.diff(np.where(np.r_[y[y != 'O'], ['B']] == 'B')[0]) 
array([3, 2, 1]) 
1

搜索排序可以幫助在這裏:

>>> y 
array(['B', 'I', 'I', 'O', 'B', 'I', 'O', 'O', 'B', 'O'], 
     dtype='|S1') 
>>> start=np.where(y=='B')[0] 
>>> end=np.where(y=='O')[0] 

>>> end[np.searchsorted(end,start)]-start 
array([3, 2, 1]) 

另一種方法:

starts = np.where(y == 'B')[0] 

一個段結束,其中一個'B''I'是:

>>> mask=np.concatenate(([True],(np.diff(end)!=1))) 
>>> mask 
array([ True, True, False, True], dtype=bool) 
>>> end[mask]-start 
array([3, 2, 1])