1

I'm trying to split a numpy array into chunks that obey a certain condition. For example, given a = np.array([ 1, 2, 3, 4, 10, 9, 8, 7, 7, 7, 8, 9, 10]) return [array([3, 4]), array([7, 7, 7])] since those chunks obey the condition np.logical_and(a>2,a<8).

The solution I came up with works, but it feels awkward since I'm applying the condition first to split the array and then again to select the results I want.

import numpy as np
a = np.array([ 1,  2,  3,  4, 10,  9,  8,  7,  7,  7,  8,  9, 10])
cond = np.logical_and(a>2,a<8)
splits = np.split(a,np.where(np.diff(cond))[0]+1)
# this yields [array([1, 2]), array([3, 4]), array([10,  9,  8]), array([7, 7, 7]), array([ 8,  9, 10])]
result = [x for x in splits if np.logical_and(x>2,x<8).any()]
# [array([3, 4]), array([7, 7, 7])]

Is there a way to apply the same condition to both so that if I wanted to change the condition I could change it once in my code instead of twice? Or am I over-complicating things where there's a much simpler, more pythonic, way of doing this?

1 Answer 1

6

Here is one option, subset the array before split to eliminate the for loop:

cond = (a > 2) & (a < 8)
np.split(a[cond], np.where(np.diff(np.where(cond)[0]) > 1)[0] + 1)
# [array([3, 4]), array([7, 7, 7])]
Sign up to request clarification or add additional context in comments.

1 Comment

That's clever. I forgot that np.where returns an array of indices exactly the same size as the subset so that the original breaks are preserved in the subset by jumps in the indices greater than 1. Thanks!

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.