# How to find the cumulative sum of numbers in a list?

PythonListSumAccumulate## Python Problem Overview

```
time_interval = [4, 6, 12]
```

I want to sum up the numbers like `[4, 4+6, 4+6+12]`

in order to get the list `t = [4, 10, 22]`

.

I tried the following:

```
t1 = time_interval[0]
t2 = time_interval[1] + t1
t3 = time_interval[2] + t2
print(t1, t2, t3) # -> 4 10 22
```

## Python Solutions

## Solution 1 - Python

If you're doing much numerical work with arrays like this, I'd suggest `numpy`

, which comes with a cumulative sum function `cumsum`

:

```
import numpy as np
a = [4,6,12]
np.cumsum(a)
#array([4, 10, 22])
```

Numpy is often faster than pure python for this kind of thing, see in comparison to @Ashwini's `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
```

But of course if it's the only place you'll use numpy, it might not be worth having a dependence on it.

## Solution 2 - Python

In Python 2 you can define your own generator function like this:

```
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]
```

And in Python 3.2+ you can use `itertools.accumulate()`

:

```
In [1]: lis = [4,6,12]
In [2]: from itertools import accumulate
In [3]: list(accumulate(lis))
Out[3]: [4, 10, 22]
```

## Solution 3 - Python

I did a bench-mark of the top two answers with Python 3.4 and I found `itertools.accumulate`

is faster than `numpy.cumsum`

under many circumstances, often much faster. However, as you can see from the comments, this may not always be the case, and it's difficult to exhaustively explore all options. (Feel free to add a comment or edit this post if you have further benchmark results of interest.)

Some timings...

For short lists `accumulate`

is about 4 times faster:

```
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
```

For longer lists `accumulate`

is about 3 times faster:

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

If the `numpy`

`array`

is not cast to `list`

, `accumulate`

is still about 2 times faster:

```
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
```

If you put the imports outside of the two functions and still return a `numpy`

`array`

, `accumulate`

is still nearly 2 times faster:

```
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
```

## Solution 4 - Python

Try the
`itertools.accumulate()`

function.

```
import itertools
list(itertools.accumulate([1,2,3,4,5]))
# [1, 3, 6, 10, 15]
```

## Solution 5 - Python

Behold:

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

Will output (as expected):

```
[4, 10, 22]
```

## Solution 6 - Python

Assignment expressions from PEP 572 (new in Python 3.8) offer yet another way to solve this:

```
time_interval = [4, 6, 12]
total_time = 0
cum_time = [total_time := total_time + t for t in time_interval]
```

## Solution 7 - Python

You can calculate the cumulative sum list in linear time with a simple `for`

loop:

```
def csum(lst):
s = lst.copy()
for i in range(1, len(s)):
s[i] += s[i-1]
return s
time_interval = [4, 6, 12]
print(csum(time_interval)) # [4, 10, 22]
```

The standard library's `itertools.accumulate`

may be a faster alternative (since it's implemented in C):

```
from itertools import accumulate
time_interval = [4, 6, 12]
print(list(accumulate(time_interval))) # [4, 10, 22]
```

## Solution 8 - Python

Since **python 3.8** it's possible to use Assignment expressions, so things like this became easier to implement

```
nums = list(range(1, 10))
print(f'array: {nums}')
v = 0
cumsum = [v := v + n for n in nums]
print(f'cumsum: {cumsum}')
```

produces

```
array: [1, 2, 3, 4, 5, 6, 7, 8, 9]
cumsum: [1, 3, 6, 10, 15, 21, 28, 36, 45]
```

The same technique can be applied to find the cum product, mean, etc.

```
p = 1
cumprod = [p := p * n for n in nums]
print(f'cumprod: {cumprod}')
s = 0
c = 0
cumavg = [(s := s + n) / (c := c + 1) for n in nums]
print(f'cumavg: {cumavg}')
```

results in

```
cumprod: [1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
cumavg: [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]
```

## Solution 9 - Python

First, you want a running list of subsequences:

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

Then you just call `sum`

on each subsequence:

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

(This isn't the most efficient way to do it, because you're adding all of the prefixes repeatedly. But that probably won't matter for most use cases, and it's easier to understand if you don't have to think of the running totals.)

If you're using Python 3.2 or newer, you can use `itertools.accumulate`

to do it for you:

```
sums = itertools.accumulate(seq)
```

And if you're using 3.1 or earlier, you can just copy the "equivalent to" source straight out of the docs (except for changing `next(it)`

to `it.next()`

for 2.5 and earlier).

## Solution 10 - Python

If You want a pythonic way without numpy working in 2.7 this would be my way of doing it

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

now let's try it and test it against all other implementations

```
import timeit, sys
L=list(range(10000))
if sys.version_info >= (3, 0):
reduce = functools.reduce
xrange = range
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
```

## Solution 11 - Python

There could be many answers for this depending on the length of the list and the performance. One very simple way which I can think without thinking of the performance is this:

```
a = [1, 2, 3, 4]
a = [sum(a[0:x]) for x in range(1, len(a)+1)]
print(a)
```

`[1, 3, 6, 10]`

This is by using list comprehension and this may work fairly well it is just that here I am adding over the subarray many times, you could possibly improvise on this and make it simple!

Cheers to your endeavor!

## Solution 12 - Python

```
values = [4, 6, 12]
total = 0
sums = []
for v in values:
total = total + v
sums.append(total)
print 'Values: ', values
print 'Sums: ', sums
```

Running this code gives

```
Values: [4, 6, 12]
Sums: [4, 10, 22]
```

## Solution 13 - Python

Try this:

```
result = []
acc = 0
for i in time_interval:
acc += i
result.append(acc)
```

## Solution 14 - Python

```
lst = [4, 6, 12]
[sum(lst[:i+1]) for i in xrange(len(lst))]
```

If you are looking for a more efficient solution (bigger lists?) a generator could be a good call (or just use `numpy`

if you really care about performance).

```
def gen(lst):
acu = 0
for num in lst:
yield num + acu
acu += num
print list(gen([4, 6, 12]))
```

## Solution 15 - Python

```
l = [1,-1,3]
cum_list = l
def sum_list(input_list):
index = 1
for i in input_list[1:]:
cum_list[index] = i + input_list[index-1]
index = index + 1
return cum_list
print(sum_list(l))
```

## Solution 16 - Python

In Python3, To find the cumulative sum of a list where the `i`

th element
is the sum of the first i+1 elements from the original list, you may do:

```
a = [4 , 6 , 12]
b = []
for i in range(0,len(a)):
b.append(sum(a[:i+1]))
print(b)
```

OR you may use list comprehension:

```
b = [sum(a[:x+1]) for x in range(0,len(a))]
```

**Output**

```
[4,10,22]
```

## Solution 17 - Python

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

This is *slighlty* faster than the generator method above by @Ashwini for small lists

```
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
```

For larger lists, the generator is the way to go for sure. . .

```
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
```

## Solution 18 - Python

Somewhat hacky, but seems to work:

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

I did think that the inner function would be able to modify the `y`

declared in the outer lexical scope, but that didn't work, so we play some nasty hacks with structure modification instead. It is probably more elegant to use a generator.

## Solution 19 - Python

Without having to use Numpy, you can loop directly over the array and accumulate the sum along the way. For example:

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

Results in:

```
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
```

## Solution 20 - Python

A pure python oneliner for cumulative sum:

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

This is a recursive version inspired by https://stackoverflow.com/questions/13347515/recursive-cumulative-sums. Some explanations:

- The first term
`X[:1]`

is a list containing the previous element and is almost the same as`[X[0]]`

(which would complain for empty lists). - The recursive
`cumsum`

call in the second term processes the current element`[1]`

and remaining list whose length will be reduced by one. `if X[1:]`

is shorter for`if len(X)>1`

.

Test:

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

And simular for cumulative product:

```
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]
```

## Solution 21 - Python

Here's another fun solution. This takes advantage of the `locals()`

dict of a comprehension, i.e. local variables generated inside the list comprehension scope:

```
>>> [locals().setdefault(i, (elem + locals().get(i-1, 0))) for i, elem
in enumerate(time_interval)]
[4, 10, 22]
```

Here's what the `locals()`

looks for each iteration:

```
>>> [[locals().setdefault(i, (elem + locals().get(i-1, 0))), locals().copy()][1]
for i, elem in enumerate(time_interval)]
[{'.0': <enumerate at 0x21f21f7fc80>, 'i': 0, 'elem': 4, 0: 4},
{'.0': <enumerate at 0x21f21f7fc80>, 'i': 1, 'elem': 6, 0: 4, 1: 10},
{'.0': <enumerate at 0x21f21f7fc80>, 'i': 2, 'elem': 12, 0: 4, 1: 10, 2: 22}]
```

Performance is not terrible for small lists:

```
>>> %timeit list(accumulate([4, 6, 12]))
387 ns ± 7.53 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> %timeit np.cumsum([4, 6, 12])
5.31 µs ± 67.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit [locals().setdefault(i, (e + locals().get(i-1,0))) for i,e in enumerate(time_interval)]
1.57 µs ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
```

And obviously falls flat for larger lists.

```
>>> l = list(range(1_000_000))
>>> %timeit list(accumulate(l))
95.1 ms ± 5.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit np.cumsum(l)
79.3 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit np.cumsum(l).tolist()
120 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit [locals().setdefault(i, (e + locals().get(i-1, 0))) for i, e in enumerate(l)]
660 ms ± 5.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
```

Even though the method is ugly and not practical, it sure is fun.

## Solution 22 - Python

I think the below code is the easiest:

```
a=[1,1,2,1,2]
b=[a[0]]+[sum(a[0:i]) for i in range(2,len(a)+1)]
```

## Solution 23 - Python

This would be Haskell-style:

```
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])
```