在Python中有效地查找大于阈值的第一个样本(和MATLAB比较)

xan*_*eon 5 python matlab numpy threshold

threshold我希望只找到a signal大于a 的第一个样本,而不是找到列表或数组中大于特定的所有样本/数据点threshold.信号可能会多次超过阈值.例如,如果我有一个示例信号:

signal = [1, 2, 3, 4, 4, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 1, 4, 8, 7, 6, 5, 0]
Run Code Online (Sandbox Code Playgroud)

和a threshold = 2,然后

signal = numpy.array(signal)
is_bigger_than_threshold = signal > threshold
Run Code Online (Sandbox Code Playgroud)

会给我所有signal超过的值threshold.但是,每当信号变得大于阈值时,我想只得到第一个样本.因此,我将浏览整个列表并进行布尔比较

first_bigger_than_threshold = list()
first_bigger_than_threshold.append(False)
for i in xrange(1, len(is_bigger_than_threshold)):
    if(is_bigger_than_threshold[i] == False):
        val = False
    elif(is_bigger_than_threshold[i]):
        if(is_bigger_than_threshold[i - 1] == False):
            val = True
        elif(is_bigger_than_threshold[i - 1] == True):
            val = False
    first_bigger_than_threshold.append(val)
Run Code Online (Sandbox Code Playgroud)

这给了我正在寻找的结果,即

[False, False, True, False, False, False, False, False, False, True, False, False, False,   
False, False, False, True, False, False, False, False, False]
Run Code Online (Sandbox Code Playgroud)

在MATLAB中,我会做同样的事情

for i = 2 : numel(is_bigger_than_threshold)
    if(is_bigger_than_threshold(i) == 0)
        val = 0;
    elseif(is_bigger_than_threshold(i))
        if(is_bigger_than_threshold(i - 1) == 0)
            val = 1;
        elseif(is_bigger_than_threshold(i - 1) == 1)
            val = 0;
        end
    end
    first_bigger_than_threshold(i) = val;
end % for
Run Code Online (Sandbox Code Playgroud)

是否有更有效(更快)的方式来执行此计算?

如果我用Python生成数据,例如

signal = [round(random.random() * 10) for i in xrange(0, 1000000)]
Run Code Online (Sandbox Code Playgroud)

并计算这些值需要4.45几秒钟.如果我在MATLAB中生成数据

signal = round(rand(1, 1000000) * 10);
Run Code Online (Sandbox Code Playgroud)

并执行程序只需0.92几秒钟.

为什么MATLAB比执行此任务的速度快5倍?

提前感谢您的意见!

HYR*_*YRY 5

其他答案给你第一个 True 的位置,如果你想要一个标记第一个 True 的 bool 数组,你可以做得更快:

import numpy as np

signal = np.random.rand(1000000)
th = signal > 0.5
th[1:][th[:-1] & th[1:]] = False
Run Code Online (Sandbox Code Playgroud)