矢量化numpy多条件嵌套循环

时间:2016-03-10 12:35:49

标签: python numpy

试图在嘈杂的周期性和准周期信号中产生自动峰值检测,由Felix Scholkmann,Jens Boss和Martin Wolf在Python中,我在实施过程中遇到了绊脚石。

在尝试优化时,我注意到嵌套的for循环在处理时间方面造成了瓶颈(平均需要115394毫秒才能完成)。 有没有更有效的方法来构造嵌套的for循环?

N.B: 参数signal是算法将处理的坐标列表,其格式为

  

-48701.0   -20914.0   -1757.0   -49278.0   -106781.0   -88139.0   -13587.0   28071.0   11880.0   -13375.0   -18056.0   -15248.0   -12476.0   -9832.0   -26365.0   -65734.0   -81657.0   -41566.0   6382.0   872.0   -30666.0   -20261.0   17543.0   6278.0   ...

列表长32768行。

该函数返回检测到的峰值的索引,并在另一个函数中处理。

def ampd(signal):

    s_time = range(1, len(signal)+1)

    [fitPolynomial, fitError] = np.polyfit(s_time, signal, 1)
    fitSignal = np.polyval([fitPolynomial, fitError], s_time)

    dtrSignal = signal - fitSignal

    N = len(dtrSignal)
    L = math.ceil(N/2.0)-1

    creation_start = time.time()
    np.random.seed(1969)

    LSM = np.random.uniform(0, 2, size=(L, N))
    creation_elapsedTime = time.time() - creation_start
    print('LSM created in %s ms' % int(creation_elapsedTime * 1000))

    loop_start = time.time()
    for k in range(1, L):
        for i in range(k+2, N-k+1):
            if signal[i-1]>signal[i-k-1] and signal[i-1]>signal[i+k-1]:
                    LSM[k,i] = 0

    loop_elapsedTime = time.time() - loop_start
    print('Loop completed in %s ms' % int(loop_elapsedTime * 1000))

    G = np.sum(LSM, axis=1)

    l = min(enumerate(G), key=itemgetter(1))[0]

    MLSM = LSM[0:l]

    S = np.std(MLSM, ddof=1)

    found_indices = np.where(MLSM == ((S-1) == 0))
    del LSM
    del MLSM

    return found_indices[1]

1 个答案:

答案 0 :(得分:2)

这是一个只使用一个循环的解决方案

for k in range(1, L):
    mat=1-((signal[k+1:N-k]>signal[1:N-2*k]) & (signal[k+1:N-k]>signal[2*k+1:N]))
    LSM[k,k+2:N-k+1]*=mat
它的速度更快,似乎也能提供相同的解决方案。您比较切片(如Ami Tavory所建议的),将比较与&结合,后者得到True/False数组;使用1-操作,将其转换为零和1,零对应于满足条件的位置。最后,你将行乘以结果。