I was writing a function in python to extract original values given a list containing cumulative sum values. For eg -
Given : cumulative_sum = [1, 3, 6, 10, 15, 21, 28, 36, 45]
Output : [1, 2, 3, 4, 5, 6, 7, 8, 9]
I came up with two functions A & B and am looking for feedback on them, especially using xrange() vs enumerate().
import numpy as np
cumulative = np.cumsum(range(1,10))
def A(cumulative):
output = [0] * len(cumulative)
for i in xrange(len(cumulative)-1):
output[-(i+1)] = cumulative[-(i+1)] - cumulative[-(i+2)]
output[0] = cumulative[0]
return output
def B(cumulative):
output = [0] * len(cumulative)
for i,e in reversed(list(enumerate(cumulative))):
output[i]=cumulative[i] - cumulative[i-1]
output[0]=cumulative[0]
return output
2 Answers 2
Both aren't great. B
is really complicated, which is unnecessary. A
has this extra negation:
output[-(i+1)] = cumulative[-(i+1)] - cumulative[-(i+2)]
You could have just used positive indices (why iterate backwards anyway?):
output[i+1] = cumulative[i+1] - cumulative[i]
I think sort of thing is best accomplished with itertools
. In particular, there's a pairwise
recipe:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
Which translates directly into what we want to do:
def C(cumulative):
yield cumulative[0]
for a, b in pairwise(cumulative):
yield b-a
This returns a generator, instead of a list, but generators are typically far more useful anyway. I feel that this approach makes it much more explicit what it is you're actually doing: you're yielding the first element, and then the pairwise difference between the rest.
Numpy's element-wise subtraction can be used to leverage the pairwise operation by shifting the cumulative sum.
import numpy as np
x = np.arange(1, 10) # desired output in OP
x_cumsum = np.cumsum(x) # given in OP
x_cumsum_shifted = np.insert(np.delete(x_cumsum, -1), 0, 0)
_x = x_cumsum - x_cumsum_shifted # the desired output in OP
For instance, if x_cumsum = [a, a+b, a+b+c, a+b+c+d]
,
and x_cumsum_shifted = [0, a, a+b, a+b+c]
,
therefore x_cumsum - x_cumsum_shifted = [a, b, c, d]
.