Summing only sequential values โ€‹โ€‹in a python array

I am new to python (and even programming!), So I will try to be as clear as I can to explain my question. It may be easy for you, but I have not yet found a satisfactory result.

Here is the problem:

I have an array with negative and positive values, for example:

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 summarize ONLY negative values โ€‹โ€‹that are continuous , i.e. only the sum (-1, -6, -6), sum (-5, - 2, -1, -4), etc. I tried using numpy.where as well as numpy.split based on the condition.

For instance:

  for i in range(len(x)): if x[i] < 0.: y[i] = sum(x[i]) 

However, as expected, I just got a summation of all the negative values โ€‹โ€‹in the array. In this case, sum (- 1, -6, -6, -5, -5, -2, -1, -4) Can the guys share with me an aesthetic and effective way to solve this problem? I would appreciate any response to this.

Thank you very much

+6
source share
3 answers

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 , for example:

 mask1 = np.convolve(mask.astype(int),np.ones(3),'same')>1 

You can also get the number of negative numbers on each "island" with a slight change to the existing code -

 counts = np.bincount(id[mask1]-1) 

Run Example -

 In [395]: x Out[395]: array([ 1, 4, 2, 3, -1, -6, -6, 5, 6, 7, 3, 1, -5, 4, 9, -5, -2, -1, -4]) In [396]: out Out[396]: array([-13., -12.]) In [397]: counts Out[397]: array([3, 4]) 
+1
source

You can use itertools , here with groupby you can group your objects based on these signs, and then check if this condition matches the key function so that it contains negative numbers, then print the amount it gives, and finally you can use the chain.from_iterable function to bind the result:

 >>> from itertools import groupby,tee,chain >>> def summ_neg(li): ... for k,g in groupby(li,key=lambda i:i<0) : ... if k: ... yield [sum(g)] ... yield g ... >>> list(chain.from_iterable(summ_neg(x))) [1, 4, 2, 3, -13, 5, 6, 7, 3, 1, -5, 4, 9, -12] 

Or, as a more pythonic way, use list comprehension:

  list(chain.from_iterable([[sum(g)] if k else list(g) for k,g in groupby(x,key=lambda i:i<0)])) [1, 4, 2, 3, -13, 5, 6, 7, 3, 1, -5, 4, 9, -12] 
+7
source

you can mark negative values โ€‹โ€‹.... and do it with simple python

 prev = False for i,v in enumerate(a): j = i + 1 if j < len(a): if a[i] < 0 and a[j] < 0: temp.append(v) prev = True elif a[i] < 0 and prev: temp.append(v) prev = True elif a[i] > 0: prev = False else: if prev and v < 0: temp.append(v) 

Output

print (temperature)

[- 1, -6, -6, -5, -2, -1, -4]

with intertools I would do just that

 def sum_conseq_negative(li): neglistAll = [] for k, g in groupby(li, key=lambda i:i<0): negList = list(g) if k and len(negList) > 1: neglistAll.extend(negList) return sum(negList), len(negList) sumOf, numOf = sum_conseq_negative(li) print("sum of negatives {} number of summed {}".format(sumOf,numOf)) 

the sum of negative numbers -25 the number of summed 7

+1
source

All Articles