如何计算Numpy数组

时间:2017-10-19 08:56:59

标签: python arrays numpy binary

我有一个像这样的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循环吗?它看起来效率不高,因为我必须在非常大的数组上运行此函数。

你有什么想法吗? 谢谢。

4 个答案:

答案 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是一个布尔数组,True0

>>> 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)中轻松完成。只要有一个计数器,每次找到零时都会增加一个,然后将计数器变量的值附加到另一个数组中,用于你在初始数组中命中的每个数组。