I have the following:

matrix1 = {{a, b, c, d}, {e, f, g, h}, {i, j, k, l}, {m, n, o, p}}

(Note that it's the data that matters, not the fact it's defined as a matrix. Could be a table, could be a list.)

I want to create a cumulative sum, so that each entry is the sum of all data in that row up to and including column n, which is the column where the sum is to be placed. In other words, I want

matrix2 = {{a, a + b, a + b + c, a + b + c + d}, {e, e + f, e + f + g, e + f + g + h}, {i, i + j, i + j + k, i + j + k + l}, {m, m + n, 
m + n + o, m + n + o + p}}

I assume there must be a way to do this using Total[matrix1 ,{2}] combined with some way to specify the number of columns to sum - maybe Range...? Or should I be using Part and Span? If so, how?

Can anyone help with this? Thanks in advance.


I first came up with:

FoldList[Plus, #[[1]], Rest[#]] & /@ matrix

Then read the documentation for Accumulate, which says it is equivalent to:

Rest[FoldList[Plus, 0, #]] & /@ matrix1

One nice thing about these approaches is they generalize beyond sums:

FoldList[Times, #[[1]], Rest[#]] & /@ matrix1
Rest[FoldList[Times, 1, #]] & /@ matrix1
| improve this answer | |

Just for fun, another approach using matrix-matrix multiplication:

acc = matrix1.UpperTriangularize[ConstantArray[1, {1, 1} Dimensions[matrix1][[2]]]];
acc // MatrixForm

$\left( \begin{array}{cccc} a & a+b & a+b+c & a+b+c+d \\ e & e+f & e+f+g & e+f+g+h \\ i & i+j & i+j+k & i+j+k+l \\ m & m+n & m+n+o & m+n+o+p \\ \end{array} \right)$

As alternative to Accumulate[matrix1], you could use

acc = LowerTriangularize[ConstantArray[1, {1, 1} Dimensions[matrix1[[1]]]].matrix1;
acc // MatrixForm

$\left( \begin{array}{cccc} a & b & c & d \\ a+e & b+f & c+g & d+h \\ a+e+i & b+f+j & c+g+k & d+h+l \\ a+e+i+m & b+f+j+n & c+g+k+o & d+h+l+p \\ \end{array} \right)$

I would not advise to use these in practice as they have comptational complexity $O(n^3)$ while the methods involving Accumulate have only complexity $O(n^2)$.

| improve this answer | |
  • $\begingroup$ Dear @Richard, you can only mark a single answer as the answer to your question (although you can upvote as many as you like). In this case, I would recommend to mark kglr's post as answer as it is (i) more concise and (ii) more efficient than mine. $\endgroup$ – Henrik Schumacher Aug 31 '18 at 9:53
  • 1
    $\begingroup$ Clever. Accumulate is probably the standard way, but I do prefer/like Linear Algebra solutions. $\endgroup$ – Anton Antonov Aug 31 '18 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.