0

New to numpy. I have a 2D array composed of ones and zeros which i'm trying to scan diagonally for a certain length of consecutive ones. Once the pattern(s) has been found the function should return the index of the pattern's beginning, ie the location of the first "1" in the stretch. This is my best attempt:

def find_pattern(array2D, patternlength):
ones_count = 0
pattern_location = []
diag = [array2D.diagonal(i) for i in range(array2D.shape[1]-1,-array2D.shape[0],-1)]
for index, match in np.ndenumerate(diag):
    if match == 1:
        ones_count +=1
    else:
        ones_count == 0
    if ones_count == patternlength:
        pattern_location.append(index)
return pattern_location

However, when trying to run this produces a ValueError:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I understand why the error is being raised but I can't figure out how to go around it. The any() or all() don't seem to be suitable in the instance that i'm looking for a certain stretch of consecutive ones.

I'm looking for a solution which doesn't involve the use of extra packages such as pandas and itertools.

Thanks!

1 Answer 1

1

I think you're overcomplicating it, how about:

import numpy as np

def find_pattern(array2D, patternlength):
    res=[]
    for k in range(-array2D.shape[0]+1, array2D.shape[1]):
        diag=np.diag(array2D, k=k)
        if(len(diag)>=patternlength):
            for i in range(len(diag)-patternlength+1):
                if(all(diag[i:i+patternlength]==1)):
                    res.append((i+abs(k), i) if k<0 else (i, i+abs(k)))
    return res

Sample input:

test=np.random.choice([0,1], (12, 14))

print(test)

print(find_pattern(test,3))

returns:

[[1 1 1 0 0 0 1 0 1 1 1 0 1 1]
 [1 1 0 0 0 1 1 1 1 0 1 0 0 1]
 [1 0 1 1 1 0 1 0 1 1 1 0 0 1]
 [1 1 0 1 0 1 1 0 0 0 1 0 0 0]
 [0 1 0 1 0 1 1 0 1 0 0 0 1 1]
 [1 1 0 0 0 1 0 1 0 1 0 1 0 0]
 [1 0 1 0 0 0 1 1 0 1 1 1 1 1]
 [1 1 1 1 1 1 0 0 0 0 0 0 0 0]
 [1 0 1 1 1 0 1 0 0 0 0 0 0 1]
 [1 0 1 0 0 1 1 1 1 1 0 1 0 0]
 [0 0 1 0 0 1 0 0 1 1 0 1 1 0]
 [0 0 0 0 0 1 1 0 1 1 0 0 0 0]]

[(6, 0), (5, 1), (6, 2), (7, 3), (7, 5), (8, 6), (9, 7), (0, 0), (1, 1), (2, 4), (3, 5), (4, 8), (0, 6), (1, 8)]
Sign up to request clarification or add additional context in comments.

2 Comments

I do have a tendency to overcomplicate things :) However I should have specified that the sequence i'm looking for won't necessarily be in the main diagonal and can be anywhere in the array (diagonally).
Cheers, I tweaked my answer - this should do the trick for you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.