Finding first samples greater than a threshold value efficiently in Python (and MATLAB comparison)
Question: Instead of finding all the samples / data points within a list or an array
which are greater than a particular `threshold`, I would like to find only the
first samples where a `signal` becomes greater than a `threshold`. The signal
might cross the threshold several times. For example if I have an example
signal:

    
    
    signal = [1, 2, 3, 4, 4, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 1, 4, 8, 7, 6, 5, 0]
    

and a `threshold = 2`, then

    
    
    signal = numpy.array(signal)
    is_bigger_than_threshold = signal > threshold
    

would give me all values in `signal`which are greater than `threshold`.
However, I would like to get only the first samples whenever signal becomes
greater than threshold. Therefore, I am going through the whole list and make
boolean comparisons like

    
    
    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)
    

This gives me the result I was looking for, namely

    
    
    [False, False, True, False, False, False, False, False, False, True, False, False, False,   
    False, False, False, True, False, False, False, False, False]
    

In MATLAB I would do similarily

    
    
    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
    

Is there a more efficient (faster) way to perform this calculation?

If I generate data in Python, e.g.

    
    
    signal = [round(random.random() * 10) for i in xrange(0, 1000000)]
    

and time it, calculating these values took `4.45` seconds. If I generate data
in MATLAB

    
    
    signal = round(rand(1, 1000000) * 10);
    

and execute the program it takes only `0.92` seconds.

Why is MATLAB almost 5 times quicker than Python performing this task?

Thanks in advance for your comments!


Answer: [This post](http://stackoverflow.com/questions/17242684/for-loop-in-python-
is-10x-slower-than-matlab) explains why your code is slower than Matlab.

Try this code

    
    
    import numpy as np
    
    threshold = 2
    signal = np.array([1, 2, 3, 4, 4, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 1, 4, 8, 7, 6, 5, 0])
    
    indices_bigger_than_threshold = np.where(signal > threshold)[0] # get item
    print indices_bigger_than_threshold
    # [ 2  3  4  5  9 16 17 18 19 20]
    non_consecutive = np.where(np.diff(indices_bigger_than_threshold) != 1)[0]+1 # +1 for selecting the next
    print non_consecutive
    # [4 5]
    first_bigger_than_threshold1 = np.zeros_like(signal, dtype=np.bool)
    first_bigger_than_threshold1[indices_bigger_than_threshold[0]] = True # retain the first
    first_bigger_than_threshold1[indices_bigger_than_threshold[non_consecutive]] = True
    

`np.where` returns indices that match the condition.

The strategy is to get indices upper than `threshold` and remove the
consecutive.

BTW, welcome to Python/Numpy world.

