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:

for i in time_interval:t1=time_interval[0]t2=time_interval[1] + t1t3=time_interval[2] + t2print(t1, t2, t3)4 10 224 10 224 10 22
  • 12
    Side note: Don't call a list list. That's the name of the built-in function used to convert other things into lists, and you don't want to hide that.– abarnertApr 8 '13 at 21:20
  • See also stackoverflow.com/q/9258602– hpauljAug 20 '16 at 14:59

16 Answers16

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 npa=[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 loopIn [137]: timeit list(accumu(xrange(1000)))10000 loops, best of 3: 147 us per loopIn [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.

  • 1
    This should have a np.cumsun case that starts with a list, to take into account the conversion time.– hpauljAug 20 '16 at 14:56
  • 2
    Good point @hpaulj, for those starting from (or aiming for) a list I would not recommend numpy.– askewchanAug 23 '16 at 19:09
  • I don't think numpy is fastest stackoverflow.com/questions/15889131/…– Chris_RandsSep 16 '16 at 15:18
  • 1
    Agreed, as I mentioned above. Avoiding reactions like yours and @hpaulj's is why I tried to limit its scope in the very first and last lines of my answer :-/– askewchanSep 16 '16 at 15:54
  • 1
    @alex: Using timeit, "if -n is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds." If you expect it to make a difference, you can supply -n 1000 to make them all equivalent.– askewchanJun 13 at 18:23

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

def accumu(lis):total=0for x in lis:total +=xyield totalIn [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 accumulateIn [3]: list(accumulate(lis))Out[3]: [4, 10, 22]

Behold:

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

Will output (as expected):

[4, 10, 22]
  • Excellent answer, and efficient as well!– AᴄʜᴇʀᴏɴғᴀɪʟMar 4 '17 at 6:28
  • 6
    Not efficient. The total expense of performing c + [c[-1] + x] over and over adds up to a total runtime quadratic in the input length.– user2357112May 22 '17 at 16:36
  • reduce is good for a one-off cumulative sum, but if you're doing a lot of calls to your cumsum function a generator will be useful to "preprocess" your cumulative_sum values and access them in O(1) for each subsequent call.– Scott SkilesJul 1 '17 at 14:06

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 timeitdef sum1(l):from itertools import accumulatereturn list(accumulate(l))def sum2(l):from numpy import cumsumreturn list(cumsum(l))l=[1, 2, 3, 4, 5]timeit(lambda: sum1(l), number=100000)# 0.4243644131347537timeit(lambda: sum2(l), number=100000)# 1.7077815784141421

For longer lists accumulate is about 3 times faster:

l=[1, 2, 3, 4, 5]*1000timeit(lambda: sum1(l), number=100000)# 19.174508565105498timeit(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 timeitdef sum1(l):from itertools import accumulatereturn list(accumulate(l))def sum2(l):from numpy import cumsumreturn cumsum(l)l=[1, 2, 3, 4, 5]*1000print(timeit(lambda: sum1(l), number=100000))# 19.18597290944308print(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 timeitfrom itertools import accumulatefrom numpy import cumsumdef sum1(l):return list(accumulate(l))def sum2(l):return cumsum(l)l=[1, 2, 3, 4, 5]*1000timeit(lambda: sum1(l), number=100000)# 19.042188624851406timeit(lambda: sum2(l), number=100000)# 35.17324400227517
  • 6
    You wouldn't expect an airplane to be faster than the train to travel across town, especially including ticket purchase and security screening. Likewise you wouldn't use numpy to process a list of five items, especially if you are unwilling to accept an array in return. If the list in question is really so short, then their running time would be inconsequential---dependencies and legibility would surely dominate. But wide usage of a list of uniform numerical data type of significant length would be silly; for that, a numpy array would be appropriate, and usually faster.– askewchanSep 16 '16 at 16:07
  • @askewchan well I don't just find this for short lists and the OP's question asks for a list as output rather than a numpy array. Perhaps you can edit your answer to be clearer on when each use is appropriate :)– Chris_RandsSep 16 '16 at 16:23
  • @askewchan In fact I've edited my answer with a much more detailed comparison. Under no circumstances, do I find numpy to be faster, unless I've overlooked something?– Chris_RandsSep 16 '16 at 18:12
  • 2
    Oh my, yes indeed :) I wouldn't say you've overlooked something, but the comparison is hard to make in isolation without considering your inputs and outputs. Most of the time in your sum2 function is probably in converting l into an array. Try timing a=np.array(l) and np.cumsum(a) separately. Then try a=np.tile(np.arange(1, 6), 1000) vs l=[1,2,3,4,5]*1000. In a program conducting other numerical processes (like the creation or loading of l in the first place) your working data would probably be in an array already, and the creation would be a constant cost.– askewchanSep 16 '16 at 18:39
  • 1
    @askewchan I got the same idea as you and therefore I did time the a=np.array(l). For the sum2 without the transformation to list, and with a numpy array as input, sum2 is 5 times faster thank sum1 in my computer in case of the long list/array.– MantxuMar 24 '17 at 15:47
values=[4, 6, 12]total=0sums=[]for v in values:total=total + vsums.append(total)print 'Values: ', valuesprint 'Sums: ', sums

Running this code gives

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

    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).

    • 7
      This runs in quadratic time (maybe that doesn't matter for the OP, but worth mentioning).– Chris TaylorApr 8 '13 at 21:24
    • First, when N=3, who cares about quadratic time? And I don't think it's overcomplicated. It's two very simple steps, each transforming one iterator into another, directly translating the English-language description. (The fact that he's using an uncommon way of defining series, where the 0-length prefix isn't counted, does make it a bit more complicated… but that's inherent in the problem, and I thought it was better to put that in the range than to hack around it by doing [1:] at the end, or to ignore it.)– abarnertApr 8 '13 at 21:26
    • Presumably the OP's actual problem isn't to get the partial sums of [4,6,12] since, as he wrote in the question, he already knows what that is!– Chris TaylorApr 8 '13 at 21:27
    • @ChrisTaylor: He explicitly said that he already knows how to write this, but wants "an easier way to write it".– abarnertApr 8 '13 at 21:35

    Try this:

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

      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 timeitL=range(10000)def sum1(l):cumsum=[]total=0for v in l:total +=vcumsum.append(total)return cumsumdef sum2(l):import numpy as npreturn 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 checksum1(L)==sum2(L)==sum3(L)==sum4(L)==this_implementation(L)>>> True # PERFORMANCE TESTtimeit.timeit('sum1(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.>>> 0.001018061637878418timeit.timeit('sum2(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.>>> 0.000829620361328125timeit.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.18932826995849608timeit.timeit('this_implementation(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.>>> 0.002348129749298096
        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 perf).

        def gen(lst):acu=0for num in lst:yield num + acuacu +=numprint list(gen([4, 6, 12]))
          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 loopIn [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 loopIn [52]: %timeit list(accumu(a))10000 loops, best of 3: 162 us per loop
          • 1
            You're timing for just 3 item list, try for 10^4 items.– Ashwini ChaudharyApr 8 '13 at 21:32
          • 1
            True, for larger lists the generator is far faster!– reptilicusApr 8 '13 at 21:33
          • I edited my answer to show that.– reptilicusApr 8 '13 at 21:35

          Somewhat hacky, but seems to work:

          def cumulative_sum(l):y=[0]def inc(n):y[0] +=nreturn 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.

            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=1while((i>0) & (i<10)):a[i]=a[i-1]+a[i]i=i+1print a

            Results in:

            [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
              def cummul_sum(list_arguement):cumm_sum_lst=[]cumm_val=0for eachitem in list_arguement:cumm_val +=eachitemcumm_sum_lst.append(cumm_val)return cumm_sum_lst

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

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

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

                    Replying to the original question asking how "to sum up numbers in a list":Check out the built-in sum() function, it probably does what you want.

                    • Not quite; he needs to turn a sequence into a series.– abarnertApr 8 '13 at 21:17
                    • Maybe. My Crystal Ball(tm) isn't good enough to say that with certainty. ;)– Ulrich EckhardtApr 8 '13 at 21:20
                    • 7
                      Well, he gives the expected output, [4, 10, 22], so you don't really need a crystal ball to know that 22 is not the right answer.– abarnertApr 8 '13 at 21:21
                    • I trusted the human language description more, i.e. how to "find the sum of numbers in a list", but you're probably right. shrug– Ulrich EckhardtApr 9 '13 at 5:18

                    protected by Antti Haapala Sep 9 '16 at 13:41

                    Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

                    Would you like to answer one of these unanswered questions instead?

                    Not the answer you're looking for? Browse other questions tagged or ask your own question.