Comment trouver la somme cumulative des numéros dans une liste?

time_interval = [4, 6, 12]

je veux faire la somme des nombres comme [4, 4+6, 4+6+12] pour obtenir la liste t = [4, 10, 22] .

j'ai essayé la suivante:

for i in time_interval:
    t1 = time_interval[0]
    t2 = time_interval[1] + t1
    t3 = time_interval[2] + t2
    print(t1, t2, t3)

4 10 22
4 10 22
4 10 22
52
demandé sur poke 2013-04-09 01:15:02

17 réponses

si vous faites beaucoup de travail numérique avec des tableaux comme celui-ci, je suggérerais numpy , qui vient avec une fonction de somme cumulative cumsum :

import numpy as np

a = [4,6,12]

np.cumsum(a)
#array([4, 10, 22])

num Python est souvent plus rapide que python pur pour ce genre de chose, voir en comparaison à de @Ashwini accumu :

In [136]: timeit list(accumu(range(1000)))
10000 loops, best of 3: 161 us per loop

In [137]: timeit list(accumu(xrange(1000)))
10000 loops, best of 3: 147 us per loop

In [138]: timeit np.cumsum(np.arange(1000))
100000 loops, best of 3: 10.1 us per loop

mais bien sûr si c'est le seul endroit où vous utiliserez numpy, il pourrait pas la peine d'avoir une dépendance sur lui.

75
répondu askewchan 2017-05-23 12:02:49

en Python 2 Vous pouvez définir votre propre fonction de générateur comme ceci:

def accumu(lis):
    total = 0
    for x in lis:
        total += x
        yield total

In [4]: list(accumu([4,6,12]))
Out[4]: [4, 10, 22]

et en Python 3.2 + vous pouvez utiliser itertools.accumulate() :

In [1]: lis = [4,6,12]

In [2]: from itertools import accumulate

In [3]: list(accumulate(lis))
Out[3]: [4, 10, 22]
61
répondu Ashwini Chaudhary 2014-05-24 10:59:10

Voici:

a = [4, 6, 12]
reduce(lambda c, x: c + [c[-1] + x], a, [0])[1:]

produira (comme prévu):

[4, 10, 22]
13
répondu wonder.mice 2015-10-09 09:43:50

j'ai fait un bench-mark des deux premières réponses avec Python 3.4 et j'ai trouvé que itertools.accumulate est plus rapide que numpy.cumsum dans de nombreuses circonstances, souvent beaucoup plus rapide. Cependant, comme vous pouvez le voir dans les commentaires, ce n'est pas toujours le cas, et il est difficile d'explorer de manière exhaustive toutes les options. (N'hésitez pas à ajouter un commentaire ou modifier ce post si vous avez d'autres résultats d'un benchmark d'intérêt.)

quelques chronométrages...

Pour listes courtes accumulate est environ 4 fois plus rapide:

from timeit import timeit

def sum1(l):
    from itertools import accumulate
    return list(accumulate(l))

def sum2(l):
    from numpy import cumsum
    return list(cumsum(l))

l = [1, 2, 3, 4, 5]

timeit(lambda: sum1(l), number=100000)
# 0.4243644131347537
timeit(lambda: sum2(l), number=100000)
# 1.7077815784141421

Pour les longues listes de accumulate est environ 3 fois plus vite:

l = [1, 2, 3, 4, 5]*1000
timeit(lambda: sum1(l), number=100000)
# 19.174508565105498
timeit(lambda: sum2(l), number=100000)
# 61.871223849244416

si le numpy array n'est pas moulé à list , accumulate est encore environ 2 fois plus rapide:

from timeit import timeit

def sum1(l):
    from itertools import accumulate
    return list(accumulate(l))

def sum2(l):
    from numpy import cumsum
    return cumsum(l)

l = [1, 2, 3, 4, 5]*1000

print(timeit(lambda: sum1(l), number=100000))
# 19.18597290944308
print(timeit(lambda: sum2(l), number=100000))
# 37.759664884768426

si vous mettez les importations en dehors des deux fonctions et encore retourner un numpy array , accumulate est encore presque 2 fois plus rapide:

from timeit import timeit
from itertools import accumulate
from numpy import cumsum

def sum1(l):
    return list(accumulate(l))

def sum2(l):
    return cumsum(l)

l = [1, 2, 3, 4, 5]*1000

timeit(lambda: sum1(l), number=100000)
# 19.042188624851406
timeit(lambda: sum2(l), number=100000)
# 35.17324400227517
8
répondu Chris_Rands 2017-03-26 17:42:08
values = [4, 6, 12]
total  = 0
sums   = []

for v in values:
  total = total + v
  sums.append(total)

print 'Values: ', values
print 'Sums:   ', sums

exécute ce code donne

Values: [4, 6, 12]
Sums:   [4, 10, 22]
3
répondu Chris Taylor 2013-04-08 21:21:29

si vous voulez une façon pythonique sans numpy travailler en 2.7 ce serait ma façon de le faire

l = [1,2,3,4]
_d={-1:0}
cumsum=[_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)]

maintenant, essayons-le et testons-le par rapport à toutes les autres implémentations

import timeit
L=range(10000)

def sum1(l):
    cumsum=[]
    total = 0
    for v in l:
        total += v
        cumsum.append(total)
    return cumsum


def sum2(l):
    import numpy as np
    return list(np.cumsum(l))

def sum3(l):
    return [sum(l[:i+1]) for i in xrange(len(l))]

def sum4(l):
    return reduce(lambda c, x: c + [c[-1] + x], l, [0])[1:]

def this_implementation(l):
    _d={-1:0}
    return [_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)]


# sanity check
sum1(L)==sum2(L)==sum3(L)==sum4(L)==this_implementation(L)
>>> True    

# PERFORMANCE TEST
timeit.timeit('sum1(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.001018061637878418

timeit.timeit('sum2(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.000829620361328125

timeit.timeit('sum3(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.4606760001182556 

timeit.timeit('sum4(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.18932826995849608

timeit.timeit('this_implementation(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.002348129749298096
3
répondu Cobry 2017-11-16 15:38:38

tout d'abord, vous voulez une liste en cours d'exécution des suites:

subseqs = (seq[:i] for i in range(1, len(seq)+1))

ensuite vous appelez juste sum sur chaque suite:

sums = [sum(subseq) for subseq in subseqs]

(ce n'est pas la façon la plus efficace de le faire, parce que vous ajoutez tous les préfixes à plusieurs reprises. Mais ce ne sera probablement pas important pour la plupart des cas d'utilisation, et il est plus facile de comprendre si vous n'avez pas à penser aux totaux en cours d'exécution.)

si vous utilisez Python 3.2 ou plus récent, vous pouvez utiliser itertools.accumulate pour le faire pour vous:

sums = itertools.accumulate(seq)

et si vous utilisez 3.1 ou plus tôt, vous pouvez simplement copier l'équivalent de la source directement à partir du docs (sauf pour changer next(it) en it.next() pour 2.5 et plus tôt).

2
répondu abarnert 2013-04-08 21:27:30

essayez ceci:

result = []
acc = 0
for i in time_interval:
    acc += i
    result.append(acc)
2
répondu MostafaR 2013-04-08 21:42:37
lst = [4,6,12]

[sum(lst[:i+1]) for i in xrange(len(lst))]

si vous cherchez une solution plus efficace (listes plus grandes?) un générateur peut être un bon choix (ou utilisez simplement numpy si vous vous souciez vraiment de perf).

def gen(lst):
    acu = 0
    for num in lst:
        yield num + acu
        acu += num

print list(gen([4, 6, 12]))
1
répondu gonz 2013-04-08 21:33:42
In [42]: a = [4, 6, 12]

In [43]: [sum(a[:i+1]) for i in xrange(len(a))]
Out[43]: [4, 10, 22]

c'est slighlty plus rapide que la méthode génératrice ci-dessus par @Ashwini pour les petites listes

In [48]: %timeit list(accumu([4,6,12]))
  100000 loops, best of 3: 2.63 us per loop

In [49]: %timeit [sum(a[:i+1]) for i in xrange(len(a))]
  100000 loops, best of 3: 2.46 us per loop

pour des listes plus larges, le générateur est la voie à suivre. . .

In [50]: a = range(1000)

In [51]: %timeit [sum(a[:i+1]) for i in xrange(len(a))]
  100 loops, best of 3: 6.04 ms per loop

In [52]: %timeit list(accumu(a))
  10000 loops, best of 3: 162 us per loop
1
répondu reptilicus 2013-04-08 21:34:49

Affectation des expressions de PEP 572 (prévu pour Python 3.8) offrent encore une autre façon de résoudre ce problème:

time_interval = [4, 6, 12]

total_time = 0
cum_time = [total_time := total_time + t for t in time_interval]
1
répondu Steven Rumbalski 2018-07-15 16:54:36

Un pur python oneliner pour la somme cumulative:

cumsum = lambda X: X[:1] + cumsum([X[0]+X[1]] + X[2:]) if X[1:] else X

C'est une version récursive inspiré par récursive sommes cumulées . Quelques explications:

  1. le premier terme X[:1] est une liste contenant l'élément précédent et est presque identique à [X[0]] (qui se plaindrait pour les listes vides).
  2. récursifs cumsum appel dans le deuxième terme traite l'élément courant [1] et la liste restante dont la longueur sera réduite d'un.
  3. if X[1:] est plus court pour if len(X)>1 .

Test:

cumsum([4,6,12])
#[4, 10, 22]

cumsum([])
#[]

et similaire pour produit cumulatif:

cumprod = lambda X: X[:1] + cumprod([X[0]*X[1]] + X[2:]) if X[1:] else X

Test:

cumprod([4,6,12])
#[4, 24, 288]
1
répondu Friedrich 2018-08-23 01:26:27

un peu hacky, mais semble fonctionner:

def cumulative_sum(l):
  y = [0]
  def inc(n):
    y[0] += n
    return y[0]
  return [inc(x) for x in l]

j'ai pensé que la fonction interne serait capable de modifier le y déclaré dans la portée lexicale externe, mais cela n'a pas fonctionné, donc nous jouons quelques coups méchants avec la modification de la structure à la place. Il est probablement plus élégant d'utiliser un générateur.

0
répondu Vatine 2013-12-30 09:52:58

sans avoir à utiliser num Py, vous pouvez boucler directement sur le tableau et accumuler la somme le long du chemin. Par exemple:

a=range(10)
i=1
while((i>0) & (i<10)):
    a[i]=a[i-1]+a[i]
    i=i+1
print a

résultats dans:

[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
0
répondu user3062149 2014-02-11 15:26:13
def cummul_sum(list_arguement):
    cumm_sum_lst = []
    cumm_val = 0
    for eachitem in list_arguement:
        cumm_val += eachitem
        cumm_sum_lst.append(cumm_val)
    return cumm_sum_lst
0
répondu Ronnie Joshua 2016-04-01 14:27:20

ce serait du style Haskell:

def wrand(vtlg):

    def helpf(lalt,lneu): 

        if not lalt==[]:
            return helpf(lalt[1::],[lalt[0]+lneu[0]]+lneu)
        else:
            lneu.reverse()
            return lneu[1:]        

    return helpf(vtlg,[0])
-1
répondu macropeter 2016-05-14 04:34:35

en réponse à la question initiale demandant comment "faire la somme des nombres dans une liste": Vérifiez la fonction de la somme intégrée (), elle fait probablement ce que vous voulez.

-9
répondu Ulrich Eckhardt 2018-03-06 18:08:42