2017-07-26 320 views
3

我有一个可能有重复的整数的整数数组。我想计算连续的相等值,当值与前一值不同时,从零开始重新计数。这是预期的结果实现了简单的Python循环:numpy:累计重复次数

import numpy as np 

def count_multiplicities(a): 
    r = np.zeros(a.shape, dtype=a.dtype) 
    for i in range(1, len(a)): 
     if a[i] == a[i-1]: 
      r[i] = r[i-1]+1 
     else: 
      r[i] = 0 
    return r 

a = (np.random.rand(20)*5).astype(dtype=int) 
a.sort() 

print "given sorted array: ", a 
print "multiplicity count: ", count_multiplicities(a) 

输出:

given sorted array: [0 0 0 0 0 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4] 
multiplicity count: [0 1 2 3 4 0 1 2 0 1 2 3 0 1 2 3 0 1 2 3] 

我怎样才能得到相同的结果,用numpy的一种有效的方法是什么?阵列非常长,但重复只是少数(不超过10次)。

在我的特殊情况下,我也知道值从零开始,并且连续值之间的差值为0或1(值中没有差距)。

+0

进一步的想法:也许一个可能的解决方案可以通过使用与给定对角线和上对角线的良好选择矩阵的乘法来实现。 –

回答

3

这里有一个cumsum基于矢量的方法 -

def count_multiplicities_cumsum_vectorized(a):  
    out = np.ones(a.size,dtype=int) 
    idx = np.flatnonzero(a[1:] != a[:-1])+1 
    out[idx[0]] = -idx[0] + 1 
    out[0] = 0 
    out[idx[1:]] = idx[:-1] - idx[1:] + 1 
    np.cumsum(out, out=out) 
    return out 

采样运行 -

In [58]: a 
Out[58]: array([0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4]) 

In [59]: count_multiplicities(a) # Original approach 
Out[59]: array([0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 0, 1, 2]) 

In [60]: count_multiplicities_cumsum_vectorized(a) 
Out[60]: array([0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 0, 1, 2]) 

运行测试 -

In [66]: a = (np.random.rand(200000)*1000).astype(dtype=int) 
    ...: a.sort() 
    ...: 

In [67]: a 
Out[67]: array([ 0, 0, 0, ..., 999, 999, 999]) 

In [68]: %timeit count_multiplicities(a) 
10 loops, best of 3: 87.2 ms per loop 

In [69]: %timeit count_multiplicities_cumsum_vectorized(a) 
1000 loops, best of 3: 739 µs per loop 

Related post

+0

谢谢!我所缺少的是'flatnonzero' –

1

我想这样的问题

import numba 
nb_count_multiplicities = numba.njit("int32[:](int32[:])")(count_multiplicities) 
X=nb_count_multiplicities(a) 

使用numba没有在所有重写你的代码,它比Divakar的矢量化的解决方案快大约50%。

如果矢量化的结果是代码更短,也更容易理解,那么矢量化会有很多用处,但是如果你强制必须矢量化代码,这对于一个非常有经验的程序员来说可能是一个问题,那么Numba就是要走的路。

+0

很高兴知道关于numba! –