0

The code down below calculates the maximum number of times consecutive positive values Cons_Pos_results, negative values Cons_Neg_results, zero values Cons_Zero_results. I am trying to implement a piece to the code to the already existing code where it shows the indexes of where the maximum number of consecutive values where between. So for the maximum number of consecutive values that are positive are between the Index 38-60. The issue for the used code: issue

Array:

import numpy as np
a = np.array([  0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.
   0.    0.    0.    0.    0.    0.    0.    0.    0.   -8.    0.    0.
 304.2 -27.8 -15.4   0.    0.  -14.8   0.    6.4  14.4   0.  -10.6  55.8
  23.1   0.   27.9  34.7  62.   23.   41.6  30.7  30.5  34.9  40.9  21.7
  31.3  19.9  32.8  26.2  14.8  18.9  15.2  23.8  21.9 112.7  38.4  34.4])

Code:

sign = np.sign(a) # we only care about the sign

def count_consecutive(arr, n):
    # pad a with False at both sides for edge cases when array starts or ends with n
    d = np.diff(np.concatenate(([False], arr == n, [False])).astype(int))
    # subtract indices when value changes from False to True from indices where value changes from True to False
    return np.flatnonzero(d == -1) - np.flatnonzero(d == 1)

Cons_Pos_results= np.max(count_consecutive(sign, 1))
Cons_Neg_results= np.max(count_consecutive(sign, 0))
Cons_Zero_results= np.max(count_consecutive(sign, -1))

Expected Output:

Consecutive Positive results: 22 Indexes: 38 - 60
Consecutive Zero results: 21     Indexes: 0 - 21
Consecutive Negative results: 2  Indexes: 26 - 27
georgehere
  • 610
  • 3
  • 12

1 Answers1

0

You can take advantage of the fact that the d array has non-zero values at the beginning and end of each found sequence. When the distance between two such non-zero values is equal to the count, you have found the desired indexes:

import numpy as np

def count_consecutive(arr, sign):
    sign_dic = {'positive':1, 'negative':-1, 'zero':0, 'pos':1, 'neg':-1, 0:0}
    n = sign_dic.get(sign, -2)
    if n == -2:
        return "sign must be 'positive', 'negative', or 'zero'."

    signs = np.sign(arr)  # we only care about the sign
    # pad a with False at both sides for edge cases when array starts or ends with n
    d = np.diff(np.concatenate(([False], signs == n, [False])).astype(int))

    # subtract indices when value changes from False to True from indices where value changes from True to False
    # get max of these
    count =  np.max(np.flatnonzero(d == -1) - np.flatnonzero(d == 1))

    # calculate starting index of longest sequence
    indexes = np.nonzero(d)
    dif = np.diff(indexes)
    i = dif[0].tolist().index(count)
    idx = indexes[0][i]

    return f'Consecutive {sign} results: {count}, Indexes: {idx} - {idx+count-1}'

a = np.array([1,1,2,3,0,0,0,0,-1,-2,0,0,0,0,0,0,0,1,1,1,1,1,1,-21])
print(count_consecutive(a, 'positive')) #Consecutive positive results: 6, Indexes: 17 - 22
print(count_consecutive(a, 'negative')) #Consecutive negative results: 2, Indexes: 8 - 9
print(count_consecutive(a, 'zero')) #Consecutive zero results: 7, Indexes: 10 - 16
pakpe
  • 5,391
  • 2
  • 8
  • 23