我有一个像这样的numpy二进制数组:
Array A = [1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0]
我想计算每个1左边有多少0,并将其返回到另一个数组中,对于这个示例,这个数组看起来像这样:
nb_1s = [0, 0, 1, 2, 2, 5]
左边的前两个没有0,所以数组的前两个数字是0等...
我知道首先我必须在我的数组中启动一个数字为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 :(得分:4)
您可以使用:
(A == 0).cumsum()[A > 0]
# array([0, 0, 1, 2, 2, 5])
或:
(~A).cumsum()[A]
# array([0, 0, 1, 2, 2, 5])
如果A
是bool数组。
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 :(得分: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
答案 2 :(得分: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])
答案 3 :(得分:1)
如果计数是累积的(根据您的示例),那么您可以在O(n)中轻松完成。只要有一个计数器,每次找到零时都会增加一个,然后将计数器变量的值附加到另一个数组中,用于你在初始数组中命中的每个数组。