Cumulative Calculations in Python: itertools.accumulate()
In Python, the itertools.accumulate()
function allows you to apply any function cumulatively. For example, it is used to calculate the cumulative sum and product of a list.
You can also calculate cumulative sums and products using functions and methods in NumPy and pandas. Refer to the following articles for details.
- NumPy: Calculate cumulative sum and product (np.cumsum, np.cumprod)
- pandas: Cumulative calculations (cumsum, cumprod, cummax, cummin)
Basic usage of itertools.accumulate()
By default, itertools.accumulate()
creates an iterator that returns cumulative sums.
It takes an iterable object like a list or tuple as an argument. Since it returns an iterator, the results are not directly displayed with print()
.
import itertools
l = [1, 2, 3, 4, 5, 6]
print(itertools.accumulate(l))
# <itertools.accumulate object at 0x1080e1a80>
print(type(itertools.accumulate(l)))
# <class 'itertools.accumulate'>
You can obtain the results sequentially using a for
loop.
for i in itertools.accumulate(l):
print(i)
# 1
# 3
# 6
# 10
# 15
# 21
To get the result as a list, use list()
. For a tuple, use tuple()
.
print(list(itertools.accumulate(l)))
# [1, 3, 6, 10, 15, 21]
To include a 0
value at the beginning, concatenate with [0]
. Alternatively, use the initial
argument, explained later (available in Python 3.8 and later).
print([0] + list(itertools.accumulate(l)))
# [0, 1, 3, 6, 10, 15, 21]
To calculate a cumulative sum in reverse order, reverse the original list using reversed()
.
print(list(itertools.accumulate(reversed(l))))
# [6, 11, 15, 18, 20, 21]
Specify the function to apply cumulatively: func
Use the func
argument to specify a function to apply cumulatively to the elements. By default, it is addition, which calculates a cumulative sum as shown in the previous section.
For example, specifying operator.mul()
as the func
argument calculates a cumulative product. Note that when specifying a callable object like a function, do not add parentheses ()
.
import itertools
import operator
print(operator.mul(2, 3))
# 6
l = [1, 2, 3, 4, 5, 6]
print(list(itertools.accumulate(l, func=operator.mul)))
# [1, 2, 6, 24, 120, 720]
The operator
module provides functions corresponding to operators like +
and *
.
Besides addition (cumulative sum) and multiplication (cumulative product), you can also apply subtraction and division cumulatively.
print(list(itertools.accumulate(l, func=operator.sub)))
# [1, -1, -4, -8, -13, -19]
print(list(itertools.accumulate(l, func=operator.truediv)))
# [1, 0.5, 0.16666666666666666, 0.041666666666666664, 0.008333333333333333, 0.001388888888888889]
Any function that takes two arguments can be used.
print(list(itertools.accumulate([1, 3, 2, 6, 5, 4], func=max)))
# [1, 3, 3, 6, 6, 6]
Lambda expressions can also be used. You can apply any process you want.
print(list(itertools.accumulate(l, func=lambda x, y: x * y)))
# [1, 2, 6, 24, 120, 720]
print(list(itertools.accumulate(l, func=lambda x, y: int(str(x) + str(y)))))
# [1, 12, 123, 1234, 12345, 123456]
The first example is equivalent to using operator.mul()
. In the second example, numbers are converted to strings, concatenated, and then converted back to integers.
Specify the initial value: initial
From Python 3.8 onwards, you can specify an initial value using the initial
argument.
Specifying a value for initial
treats it as the first element, thus increasing the result's element count by one. The default is initial=None
.
import itertools
l = [1, 2, 3, 4, 5, 6]
print(list(itertools.accumulate(l)))
# [1, 3, 6, 10, 15, 21]
print(list(itertools.accumulate(l, initial=0)))
# [0, 1, 3, 6, 10, 15, 21]
print(list(itertools.accumulate(l, initial=100)))
# [100, 101, 103, 106, 110, 115, 121]