Рассчитать накопленную сумму из последней ненулевой записи в питоне - PullRequest
4 голосов
/ 13 июня 2019

У меня есть числовой ряд типа [0,0,0,0,1,1,1,0,0,1,1,0].Я хотел бы рассчитать числовую сумму из последних ненулевых значений.то есть cumsum будет сброшен в ноль, как только будет введен ноль.

input: [0,0,0,0,1,1,1,0,0,1,1,0]
output:[0,0,0,0,1,2,3,0,0,1,2,0] 

Есть ли встроенная функция python, способная достичь этого?Или лучший способ рассчитать это без цикла?

Ответы [ 2 ]

7 голосов
/ 13 июня 2019

Вы можете сделать это с помощью itertools.accumulate.Он принимает функцию с двумя аргументами, где первый аргумент - это накопленный результат, а второй аргумент - текущий элемент из итерируемого, поэтому вы можете использовать довольно простую лямбду для вычисления промежуточного итога, если текущий элемент не равен нулю.

from itertools import accumulate

nums = [0,0,0,0,1,1,1,0,0,1,1,0]

result = accumulate(nums, lambda acc, elem: acc + elem if elem else 0)
print(list(result))
# [0, 0, 0, 0, 1, 2, 3, 0, 0, 1, 2, 0]
1 голос
/ 13 июня 2019

Мы можем сделать это за два прохода np.cumsum(..).Сначала мы вычисляем cumsum массива:

a = np.array([0,0,0,0,1,1,1,0,0,1,1,0])
c = np.cumsum(a)

Это дает нам:

>>> c
array([0, 0, 0, 0, 1, 2, 3, 3, 3, 4, 5, 5])

Затем мы фильтруем a по элементам, значение которых равно 0, и мыпоэлементно вычислите разницу между этим элементом и его предшественником:

corr = np.diff(np.hstack(((0,), c[a == 0])))

, тогда это исправление, которое мы должны применить к этим элементам:

>>> corr
array([0, 0, 0, 0, 3, 0, 2])

Затем мы можем сделать копию a (или сделайте это на месте) и вычтите исправление:

a2 = a.copy()
a2[a == 0] -= corr

это даст нам:

>>> a2
array([ 0,  0,  0,  0,  1,  1,  1, -3,  0,  1,  1, -2])

, и теперь мы можем вычислить кумулятивную сумму a2, которая будетСброс на 0 для 0, так как коррекция отслеживает приращения между:

>>> a2.cumsum()
array([0, 0, 0, 0, 1, 2, 3, 0, 0, 1, 2, 0])

или как функция:

import numpy as np

def cumsumreset(iterable, reset=0):
    a = np.array(iterable)
    c = a.cumsum()
    a2 = a.copy()
    filter = a == reset
    a2[filter] -= np.diff(np.hstack(((0,), c[filter])))
    return a2.cumsum()

, тогда это дает нам:

>>> cumsumreset([0,0,0,0,1,1,1,0,0,1,1,0])
array([0, 0, 0, 0, 1, 2, 3, 0, 0, 1, 2, 0])
...