Суммирование только последовательных значений в массиве python
Я новичок в Python (и даже Программирование!), поэтому я постараюсь как можно яснее объяснить мой вопрос. Для вас, ребята, это может быть легко, но я пока не нашел удовлетворительного результата.
вот в чем проблема:
у меня есть массив с отрицательными и положительными значениями, скажем:
x = numpy.array([1, 4, 2, 3, -1, -6, -6, 5, 6, 7, 3, 1, -5, 4, 9, -5, -2, -1, -4])
Я хотел бы суммировать только отрицательный значения постоянной, т. е. sum(-1, -6, -6), sum(-5, -2, -1, -4) и так далее. Я пробовал использовать и NumPy.где, а также и NumPy.сплит в зависимости от состояния.
например:
for i in range(len(x)):
if x[i] < 0.:
y[i] = sum(x[i])
однако, как вы можете ожидать, я просто получил суммирование всех отрицательных значений в массиве. В этом случае sum(-1, -6, -6, -5, -5, -2, -1, -4) Могли бы ребята поделиться со мной эстетическим и эффективным способом решения этой проблемы? Буду признателен за любой ответ на этом.
большое спасибо
3 ответов
вот векторизованное Нумпитоническое решение -
# 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])
вы также можете использовать np.convolve
и mask1
, вот так -
mask1 = np.convolve(mask.astype(int),np.ones(3),'same')>1
вы также можете получить количество отрицательных чисел в каждом "острове" с небольшой настройкой существующего кода -
counts = np.bincount(id[mask1]-1)
образец выполнения -
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])
можно использовать itertools
модуль, здесь с использованием groupby
вы можете группировать свои элементы на основе этих знаков, а затем проверить, соответствует ли он условию в key
функция, поэтому она содержит отрицательные числа, а затем дает сумму, другую, и, наконец, вы можете использовать chain.from_iterable
функция для цепочки результата:
>>> 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]
или как более питонический способ использовать понимание списка:
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]
вы можете отметить отрицательные значения .... и сделайте это с помощью простого 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)
выход
печать (temp)
[-1, -6, -6, -5, -2, -1, -4]
С intertools я бы это сделал
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))
сумма негативов -25 количество суммированных 7