Statistical programming, matrix languages, and more

Cumulative Sum by Rows

Accepted Solution Solved
Reply
New Contributor
Posts: 3
Accepted Solution

Cumulative Sum by Rows

A simple module for finding row-wise cumulative sum in IML:

Proc IML;


Start rowcumsum(x);
      Step1 = cusum(x);
      Step2 = 0 // Step1[1:nrow(Step1)-1,ncol(Step1)];
      Output = Step1 - repeat(Step2,1,ncol(Step1));
      return(Output);
Finish rowcumsum;

a = {1 2 3,4 5 6, 7 8 9};
SASCUSUM = cusum(a);
ROWCUSUM = rowcumsum(a);

print a; print SASCUSUM; Print ROWCUSUM;
Quit;

a

01 02 03

04 05 06

07 08 09

 

SASCUSUM

01 03 06

10 15 21

28 36 45

 

ROWCUSUM

01 03 06

04 09 15

07 15 24


Accepted Solutions
Solution
2 weeks ago
SAS Super FREQ
Posts: 3,406

Cumulative Sum by Rows

You didn't ask a question, so I can't tell whether you are saying "here is how to do this" or whether you are asking "is this the best way to do this."

If the former, yes, this is a good way to compute cumulative sums across rows of a matrix.It is a clever algorithm.

If you are asking whether this is the fastest way, I'll offer two observations: you can use the LAG function (introduced in SAS/IML 9.22) to speed up Step2, and you don't need the REPEAT function when forming the OUTPUT matrix. Thus the following code is slightly more efficient:

start rs(x);

   Step1 = cusum(x);

   Step2 = lag(Step1[,ncol(Step1)], 1); /* returns missing in Step2[1] */

   Step2[1] = 0; /* replace missing value with 0 */

   Output = Step1 - Step2;

   return( Output);

finish;

Unless your matrices are huge, it doesn't really matter which module you run. In fact, unless the number of rows is huge, you can just use a simple DO loop and the computation is just as fast:

Output = j(nrow(x), ncol(x));

do i = 1 to nrow(x);

   Output[i,] = cusum(x[i,]);

end;

View solution in original post


All Replies
Solution
2 weeks ago
SAS Super FREQ
Posts: 3,406

Cumulative Sum by Rows

You didn't ask a question, so I can't tell whether you are saying "here is how to do this" or whether you are asking "is this the best way to do this."

If the former, yes, this is a good way to compute cumulative sums across rows of a matrix.It is a clever algorithm.

If you are asking whether this is the fastest way, I'll offer two observations: you can use the LAG function (introduced in SAS/IML 9.22) to speed up Step2, and you don't need the REPEAT function when forming the OUTPUT matrix. Thus the following code is slightly more efficient:

start rs(x);

   Step1 = cusum(x);

   Step2 = lag(Step1[,ncol(Step1)], 1); /* returns missing in Step2[1] */

   Step2[1] = 0; /* replace missing value with 0 */

   Output = Step1 - Step2;

   return( Output);

finish;

Unless your matrices are huge, it doesn't really matter which module you run. In fact, unless the number of rows is huge, you can just use a simple DO loop and the computation is just as fast:

Output = j(nrow(x), ncol(x));

do i = 1 to nrow(x);

   Output[i,] = cusum(x[i,]);

end;

New Contributor
Posts: 3

Cumulative Sum by Rows

Thanks for the variations, Rick. I just wanted to share the piece of code that I repeatedly found useful.

My co's yet to make the step up from 9.20, which is slightly irritating because 9.22 has a decent set of functions introduced ... so instead of say, cuprod(x) which is available in 9.22, I use exp(cusum(log(x)))

The loop increases the computation time drastically if this function is used within an optimization code. I noticed IML has this amazing speed-up (nearly 15x) for vectorized vs loop section (similar results to your blog post on running mean and variance).The results were a bit surprising because MATLAB hardly produced a 1.5x speedup for the same optimization code, and a fully vectorized optimization code in IML runs 3x faster than the same code in MATLAB!

SAS Super FREQ
Posts: 3,406

Cumulative Sum by Rows

Impressive results! Congratulations, and thanks for sharing!

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 3 replies
  • 1481 views
  • 0 likes
  • 2 in conversation