HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Extracting original values from cumulative sum values

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
originalcumulativeextractingsumvaluesfrom

Problem

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

Solution

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.

Code Snippets

output[-(i+1)] = cumulative[-(i+1)] - cumulative[-(i+2)]
output[i+1] = cumulative[i+1] - cumulative[i]
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)
def C(cumulative):
    yield cumulative[0]
    for a, b in pairwise(cumulative):
        yield b-a

Context

StackExchange Code Review Q#117183, answer score: 5

Revisions (0)

No revisions yet.