python ndarray find_关于python:在numpy数组中查找非零之前的零个数

我有一个numpy数组A。 我想以一种有效的方式返回A中非零之前的零数,因为它在循环中。

如果A = np.array([0,1,2]),则np.nonzero(A)[0][0]返回1。但是,如果A = np.array([0,0,0]),则不起作用(在这种情况下,我希望答案3)。 而且,如果A很大,并且第一个非零在开始附近,这似乎效率很低。

相关问题:stackoverflow.com/questions/7632963/

相关票务:github.com/numpy/numpy/issues/2269

@ shx2嗯..该票证基本上在2年前就停止了,然后指向另一个在10个月前无声的票证。

这是一个迭代的Cython版本,如果这是一个严重的瓶颈,这可能是您最好的选择

# saved as file count_leading_zeros.pyx

import numpy as np

cimport numpy as np

cimport cython

DTYPE = np.int

ctypedef np.int_t DTYPE_t

@cython.boundscheck(False)

def count_leading_zeros(np.ndarray[DTYPE_t, ndim=1] a):

cdef int elements = a.size

cdef int i = 0

cdef int count = 0

while i < elements:

if a[i] == 0:

count += 1

else:

return count

i += 1

return count

这类似于@mtrw的答案,但以本机速度进行索引。我的Cython有点粗略,因此可能需要进一步改进。

使用几种不同的方法使用IPython快速测试一个非常有利的情况

In [1]: import numpy as np

In [2]: import pyximport; pyximport.install()

Out[2]: (None, )

In [3]: import count_leading_zeros

In [4]: %paste

def count_leading_zeros_python(x):

ctr = 0

for k in x:

if k == 0:

ctr += 1

else:

return ctr

return ctr

## -- End pasted text --

In [5]: a = np.zeros((10000000,), dtype=np.int)

In [6]: a[5] = 1

In [7]:

In [7]: %timeit np.min(np.nonzero(np.hstack((a, 1))))

10 loops, best of 3: 91.1 ms per loop

In [8]:

In [8]: %timeit np.where(a)[0][0] if np.shape(np.where(a)[0])[0] != 0  else np.shape(a)[0]

10 loops, best of 3: 107 ms per loop

In [9]:

In [9]: %timeit count_leading_zeros_python(a)

100000 loops, best of 3: 3.87 μs per loop

In [10]:

In [10]: %timeit count_leading_zeros.count_leading_zeros(a)

1000000 loops, best of 3: 489 ns per loop

但是,只有在我有证据(通过探查器)证明这是一个瓶颈时,我才使用这种方法。许多事情看似效率低下,但绝对不值得您花时间去修复。

+1用于不创建临时数组

+1进行测试。 有趣的是,即使迭代次数很少,Python循环也比Cython慢10倍。 如果非零元素后来在大型阵列中,则Cython的优势将更大。

i = np.argmax(A!=0)

if i==0 and np.all(A==0): i=len(A)

这应该是没有扩展的最高性能的解决方案。也可以轻松地矢量化以沿多个轴起作用。

奇怪的是,在我看来,这似乎要慢得多。 大约30毫秒。 你得到了什么?

不知道; 相较于什么? 我希望性能与非零相似,只是我们避免构造非零输出数组。

一个有趣的比较将与代码@ Mr-E测试。

通过在数组的末尾添加一个非零数字,您仍然可以使用np.nonzero获得所需的结果。

A = np.array([0,1,2])

B = np.array([0,0,0])

np.min(np.nonzero(np.hstack((A, 1))))   # --> 1

np.min(np.nonzero(np.hstack((B, 1))))   # --> 3

我很惊讶为什么没人还没有使用np.where

np.where(a)[0][0] if np.shape(np.where(a)[0])[0] != 0 else np.shape(a)[0]可以解决问题

>> a = np.array([0,1,2])

>> np.where(a)[0][0] if np.shape(np.where(a)[0])[0] != 0  else np.shape(a)[0]

... 1

>> a = np.array([0,0,0))

>> np.where(a)[0][0] if np.shape(np.where(a)[0])[0] != 0  else np.shape(a)[0]

... 3

>> a = np.array([1,2,3))

>> np.where(a)[0][0] if np.shape(np.where(a)[0])[0] != 0  else np.shape(a)[0]

... 0

天真的方法有什么问题:

def countLeadingZeros(x):

""" Count number of elements up to the first non-zero element, return that count"""

ctr = 0

for k in x:

if k == 0:

ctr += 1

else: #short circuit evaluation, we found a non-zero so return immediately

return ctr

return ctr #we get here in the case that x was all zeros

一旦找到非零元素,此函数即返回,因此在最坏的情况下为O(n)。您可以通过将其移植到C来使其更快,但是值得进行测试,以查看对您使用的阵列是否真的必要。

如果您不在乎速度,那么我有个小窍门:

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

t = np.where(a==0,1,0)+np.append(np.where(a==0,0,1),0)[1:]

print t

[1 2 1 1 0]

np.where(t==2)

(array([1]),)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值