If I have z = cumsum( [ 0, 1, 2, 6, 9 ] )
, which gives me z = [ 0, 1, 3, 9, 18 ]
, how can I get back to the original array [ 0, 1, 2, 6, 9 ]
?

- 105,000
- 18
- 159
- 188

- 18,866
- 8
- 51
- 70
5 Answers
z[1:] -= z[:-1].copy()
Short and sweet, with no slow Python loops. We take views of all but the first element (z[1:]
) and all but the last (z[:-1]
), and subtract elementwise. The copy makes sure we subtract the original element values instead of the values we're computing. (On NumPy 1.13 and up, you can skip the copy
call.)

- 260,549
- 28
- 431
- 505
-
I don't think this works, I'm getting this error message: AttributeError: 'list' object has no attribute 'copy' – Pedro Jul 29 '16 at 20:31
-
@Pedro: That's because you're using a list instead of an array. Despite the question's notation, `np.cumsum` returns an array. – user2357112 Jul 29 '16 at 20:32
-
Thanks, your answer is brilliant! I imagine this is what is going on behind the scenes for np.diff. If not, maybe it should be. – scottlittle Jul 29 '16 at 21:54
-
As a person not very familiar with Python syntax, I'm a bit lost as to what's going on here. I'd love to see an explanation in the question! :) – Jeff B Aug 24 '16 at 22:21
-
1@JeffBridgman: It's a very NumPy-specific way of doing things, so general Python syntax knowledge wouldn't help much. Particularly, if you tried this with `z = [ 0, 1, 3, 9, 18 ]` like the question says, you'd just get an `AttributeError`, since `z` really has to be a NumPy array instead of a list. (`np.cumsum` gives an array, so for the purposes of inverting `np.cumsum`, this code works fine.) I'd recommend checking out the [NumPy tutorial](https://docs.scipy.org/doc/numpy-dev/user/quickstart.html), particularly the "Basic Operations" and "Indexing, Slicing and Iterating" sections. – user2357112 Aug 26 '16 at 04:49
You can use np.diff
to compute elements 1...N
which will take the difference between any two elements. This is the opposite of cumsum
. The only difference is that diff
will not return the first element, but the first element is the same in the original and cumsum
output so we just re-use that value.
orig = np.insert(np.diff(z), 0, z[0])
Rather than insert
, you could also use np.concatenate
orig = np.concatenate((np.array(z[0]).reshape(1,), np.diff(z)))
We could also just copy and replace elements 1...N
orig = z.copy()
orig[1:] = np.diff(z)

- 64,497
- 14
- 82
- 101
If you want to keep z
, you can use np.ediff1d
:
x = np.ediff1d(z, to_begin=z[0])

- 1,125
- 9
- 14