Python 大序列过零计数的不同结果

Python 大序列过零计数的不同结果,python,numpy,Python,Numpy,此问题源于查看有关计数数量的问题的答案。提供了几个解决问题的答案,但NumPy在时间方面摧毁了其他答案 然而,当我比较四个答案时,我注意到NumPy解决方案为大序列提供了不同的结果。有问题的四个答案是、和 问题:为什么NumPy解决方案提供的结果与其他三个不同?(哪一个是正确的?) 以下是计算过零次数的结果: Blazing fast NumPy solution total time: 0.303605794907 sec Zero Crossings Small: 8 Zero Crossi

此问题源于查看有关计数数量的问题的答案。提供了几个解决问题的答案,但NumPy在时间方面摧毁了其他答案

然而,当我比较四个答案时,我注意到NumPy解决方案为大序列提供了不同的结果。有问题的四个答案是、和

问题:为什么NumPy解决方案提供的结果与其他三个不同?(哪一个是正确的?)

以下是计算过零次数的结果:

Blazing fast NumPy solution
total time: 0.303605794907 sec
Zero Crossings Small: 8
Zero Crossings Med: 54464
Zero Crossings Big: 5449071

Loop solution
total time: 15.6818780899 sec
Zero Crossings Small: 8
Zero Crossings Med: 44960
Zero Crossings Big: 4496847

Simple generator expression solution
total time: 16.3374049664 sec
Zero Crossings Small: 8
Zero Crossings Med: 44960
Zero Crossings Big: 4496847

Modified generator expression solution
total time: 13.6596589088 sec
Zero Crossings Small: 8
Zero Crossings Med: 44960
Zero Crossings Big: 4496847
以及用于获得结果的代码:

import time
import numpy as np

def zero_crossings_loop(sequence):
    s = 0
    for ind, _ in enumerate(sequence):
        if ind+1 < len(sequence):
            if sequence[ind]*sequence[ind+1] < 0:
                s += 1
    return s

def print_three_results(r1, r2, r3):
    print 'Zero Crossings Small:', r1
    print 'Zero Crossings Med:', r2
    print 'Zero Crossings Big:', r3
    print '\n'

small = [80.6, 120.8, -115.6, -76.1, 131.3, 105.1, 138.4, -81.3, -95.3, 89.2, -154.1, 121.4, -85.1, 96.8, 68.2]
med = np.random.randint(-10, 10, size=100000)
big = np.random.randint(-10, 10, size=10000000)

print 'Blazing fast NumPy solution'
tic = time.time()
z1 = (np.diff(np.sign(small)) != 0).sum()
z2 = (np.diff(np.sign(med)) != 0).sum()
z3 = (np.diff(np.sign(big)) != 0).sum()
print 'total time: {0} sec'.format(time.time()-tic)
print_three_results(z1, z2, z3)

print 'Loop solution'
tic = time.time()
z1 = zero_crossings_loop(small)
z2 = zero_crossings_loop(med)
z3 = zero_crossings_loop(big)
print 'total time: {0} sec'.format(time.time()-tic)
print_three_results(z1, z2, z3)

print 'Simple generator expression solution'
tic = time.time()
z1 = sum(1 for i, _ in enumerate(small) if (i+1 < len(small)) if small[i]*small[i+1] < 0)
z2 = sum(1 for i, _ in enumerate(med) if (i+1 < len(med)) if med[i]*med[i+1] < 0)
z3 = sum(1 for i, _ in enumerate(big) if (i+1 < len(big)) if big[i]*big[i+1] < 0)
print 'total time: {0} sec'.format(time.time()-tic)
print_three_results(z1, z2, z3)

print 'Modified generator expression solution'
tic = time.time()
z1 = sum(1 for i in xrange(1, len(small)) if small[i-1]*small[i] < 0)
z2 = sum(1 for i in xrange(1, len(med)) if med[i-1]*med[i] < 0)
z3 = sum(1 for i in xrange(1, len(big)) if big[i-1]*big[i] < 0)
print 'total time: {0} sec'.format(time.time()-tic)
print_three_results(z1, z2, z3)
导入时间
将numpy作为np导入
def零交叉点环路(顺序):
s=0
对于ind,枚举中的uu(顺序):
如果ind+1
您的解决方案对零的处理不同。numpy.diff解决方案仍然会返回一个从-1到0或从1到0的差,将其作为零交叉进行计算,而您的迭代解决方案不会,因为它们使用小于零的乘积作为标准。相反,测试
当一个数据元素等于零时,迭代和numpy解决方案都不能很好地计算交叉点。对于数据[1,0,-1],迭代解给出0个交叉点,numpy解给出2个交叉点,这两个交叉点似乎都不正确

一种解决方案是删除等于零的数据元素。在NumPy,你可以尝试类似的东西

def numpy_zero_crossings(data):
    return (np.diff(np.sign(data)[np.nonzero(data)]) != 0).sum()

但是,这会在数组中引入另一个迭代,因此它会将运行时间增加另一个O(n)

我得到与循环相同的结果,具体如下:

((array[:-1] * array[1:]) < 0).sum()
UDPATE

此版本避免了零的问题:

def numpy_zero_crossings2(array):
    nonzero_array = array[np.nonzero(array)]
    return ((nonzero_array[:-1] * nonzero_array[1:]) < 0).sum()
但是seesm要快一点:

%timeit numpy_zero_crossings2(big)
1 loops, best of 3: 194 ms per loop
vs:


旁白:现在,你的非numpy方法(将它们视为你的参考行为)会说[-1,0,1,0,-1]从未过零,因为你只在一步过零时寻找。这就是你想要的吗?这是我对原始问题的解释。我会让问题的作者来决定什么是正确的。很好的观察@Rahullia可能对此感兴趣。这实际上比numpy.diff/numpy.sign解决方案快。很酷@拉胡里亚,这比快还快!通过使用
计算零和交叉(或不)的选项,您可以将此作为答案发布在这里:并指出它可以解决计算零和不计算零的两种情况。
def numpy_zero_crossings2(array):
    nonzero_array = array[np.nonzero(array)]
    return ((nonzero_array[:-1] * nonzero_array[1:]) < 0).sum()
>>> numpy_zero_crossings2(big) == numpy_zero_crossings(big)     
True
%timeit numpy_zero_crossings2(big)
1 loops, best of 3: 194 ms per loop
%timeit numpy_zero_crossings(big)
1 loops, best of 3: 227 ms per loop