2017-10-19 46 views
4

我有一個numpy的二進制數組是這樣的:如何在每個人的左邊的numpy的數組數零的個數

Array A = [1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0] 

我想看看有多少0在每個左邊是有1,並且在其它陣列看起來像這樣對這個這個例子返回它:

nb_1s = [0, 0, 1, 2, 2, 5] 

有在左側沒有0爲兩個第一1S所以陣列的第一兩個數字是0等等......

I K現在首先我必須啓動與1的個數陣列,我的數組:

def give_zeros(binary_array): 
    binary_array = np.asarray(binary_array) 
    nb_zeros = np.zeros(binary_array.sum()) 


    return nb_zeros 

但我不知道如何來算零的個數。我應該用'nditer'在for循環中迭代嗎?它看起來並不高效,因爲我將不得不在非常大的數組上運行此函數。

你有什麼想法嗎? 謝謝。

+0

不應該認爲是:'[0,0,1,1,0,3]'? – Divakar

+0

計數是否累計? – alvas

+0

是計數是累積的,最後1在其左相鄰3個零,加上1秒 – user2505650

回答

3

下面是從的1s指數範圍陣列的分化量化的方式 -

def leftzeros_count(a): 
    idx = np.flatnonzero(a!=0) 
    return idx - np.arange(len(idx)) 

樣品試驗 -

In [298]: a = np.array([1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0]) 

In [299]: leftzeros_count(a) 
Out[299]: array([0, 0, 1, 2, 2, 5]) 

In [300]: a = np.array([0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0]) 

In [301]: leftzeros_count(a) 
Out[301]: array([1, 1, 2, 3, 3, 6]) 

In [302]: a = np.array([0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1]) 

In [303]: leftzeros_count(a) 
Out[303]: array([ 1, 1, 2, 3, 3, 6, 10]) 

運行測試

對於時機,讓瓷磚給定的樣本大量的時間和時間的量化方法 -

In [7]: a = np.array([1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0]) 

In [8]: a = np.tile(a,100000) 

# @Eric Duminil's soln 
In [9]: %timeit (a == 0).cumsum()[a > 0] 
100 loops, best of 3: 10.9 ms per loop 

# Proposed in this post 
In [10]: %timeit leftzeros_count(a) 
100 loops, best of 3: 3.71 ms per loop 
+0

您的回答,我想答案這個數組:[1,0,0,1,1,1,0,0,0,0,1,0,0,1,0],但函數返回:[2,4,4,4,8, 10],它應該是:[0,2,2,6,8] – user2505650

+0

@ user2505650請檢查編輯。我已經更新了一個新的方法。 – Divakar

+0

在'nonzero'之前直接使用'nonzero'沒有'flatnonzero'調用'ravel'會更好。 – alvas

2

在非矢量化方式:

>>> x = [1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0] 
>>> c, y = 0, [] 
>>> for i in x: 
...  if i == 1: 
...   y.append(c) 
...  else: 
...   c += 1 
... 
>>> y 
[0, 0, 1, 2, 2, 5] 

對於矢量化的解決方案,請參閱@ Divakar的回答是:

numpy,先找到非零指數,與np.nonzero()

>>> np.nonzero(x)[0] 
array([ 0, 1, 3, 5, 6, 10]) 

然後減去具有索引的長度的範圍內的數組:

>>> idx = np.nonzero(x)[0] 
>>> np.arange(len(idx)) 
array([0, 1, 2, 3, 4, 5]) 
>>> np.nonzero(x)[0] - np.arange(len(idx)) 
array([0, 0, 1, 2, 2, 5]) 

>>> np.arange(x.count(1)) 
array([0, 1, 2, 3, 4, 5]) 
>>> np.nonzero(x)[0] - np.arange(x.count(1)) 
array([0, 0, 1, 2, 2, 5]) 
+0

是後2個0,雖然不NumPy的。 –

+0

這與我的解決方案有何不同? – Divakar

+0

@Divakar,沒有太大的區別,只是'flatnonzero'有一個多餘的'拉威爾()'一步,P – alvas

1

如果計數是累積的(根據你的例子),那麼你可以很容易地爲O做到這一點(N )。只要有一個每次通過提高你找到一個零,則計數器變量的值追加到另一個陣列,每一個您的初始陣列中打了一個櫃檯。

+0

確實。見https://stackoverflow.com/a/46826684/6419007 –

+0

@EricDuminil授予您提供了一個簡潔的解決方案,我並不贊成,這樣一個簡單的問題提供了直線上升的代碼的解決方案。它進一步複製和粘貼編程,這污染了世界各地的代碼庫。只是我2美分(和明確的意見爲準)。 –

+1

感謝您的評論。我瞭解你的觀點。我非常欣賞numpy的簡潔語法,並且無法拒絕寫一些東西。 –

4

代碼

你可以使用:

(A == 0).cumsum()[A > 0] 
# array([0, 0, 1, 2, 2, 5]) 

或:

(~A).cumsum()[A] 
# array([0, 0, 1, 2, 2, 5]) 

如果A是一個布爾數組。

說明

A == 0是一個布爾數組是True每個0

>>> import numpy as np 
>>> A = np.array([1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0]) 
>>> A == 0 
array([False, False, True, False, True, False, False, True, True, 
     True, False, True, True, True, True], dtype=bool) 

您可以使用cumsum()來算的True S上的號碼:

>>> (A == 0).cumsum() 
array([0, 0, 1, 1, 2, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9]) 

你只需要其中A > 0的值:

>>> (A == 0).cumsum()[A > 0] 
array([0, 0, 1, 2, 2, 5]) 

完成!

+1

這似乎是最pythonic,如果不是最有效的解決方案 –

+0

@DanielF:謝謝。事實上,接受的答案比我的代碼快20%。 –

+1

像往常一樣,有錯誤的方式,正確的方式和@Divakar的方式 - 這有點像正確的方式,但有更多的代碼,但以某種方式更快。 –

相關問題