3
\$\begingroup\$

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
Barry
18.5k1 gold badge40 silver badges92 bronze badges
asked Jan 18, 2016 at 21:08
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

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.

answered Jan 18, 2016 at 21:46
\$\endgroup\$
1
\$\begingroup\$

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

answered Dec 16, 2020 at 20:23
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.