I am new on python (and even programing!), so I will try to be as clear as I can to explain my question. For you guys it could be easy, but I have not found a satisfactory result on this yet.
Here is the problem:
I have an array with both negative and positive values, say:
x = numpy.array([1, 4, 2, 3, -1, -6, -6, 5, 6, 7, 3, 1, -5, 4, 9, -5, -2, -1, -4])
I would like to sum ONLY the negative values that are continuous, i.e. only sum(-1, -6, -6), sum(-5, -2, -1, -4) and so on. I have tried using numpy.where, as well as numpy.split based on the condition.
for i in range(len(x)): if x[i] < 0.: y[i] = sum(x[i])
However, as you can expect, I just got the summation of all negative values in the array instead. In this case sum(-1, -6, -6, -5, -5, -2, -1, -4)
Could guys share with me an aesthetic and efficient way to solve this problem? I will appreciate any response on this.
Thank you very much
Here’s a vectorized NumPythonic solution –
# Mask of negative numbers mask = x<0 # Differentiation between Consecutive mask elements. We would look for # 1s and -1s to detect rising and falling edges in the mask corresponding # to the islands of negative numbers. diffs = np.diff(mask.astype(int)) # Mask with 1s at start of negative islands start_mask = np.append(True,diffs==1) # Mask of negative numbers with islands of one isolated negative numbers removed mask1 = mask & ~(start_mask & np.append(diffs==-1,True)) # ID array for IDing islands of negative numbers id = (start_mask & mask1).cumsum() # Finally use bincount to sum elements within their own IDs out = np.bincount(id[mask1]-1,x[mask1])
You can also use
np.convolve to get
mask1, like so –
mask1 = np.convolve(mask.astype(int),np.ones(3),'same')>1
You can also get the count of negative numbers in each “island” with a little tweak to existing code –
counts = np.bincount(id[mask1]-1)
Sample run –
In : x Out: array([ 1, 4, 2, 3, -1, -6, -6, 5, 6, 7, 3, 1, -5, 4, 9, -5, -2, -1, -4]) In : out Out: array([-13., -12.]) In : counts Out: array([3, 4])