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
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;
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;
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!
Impressive results! Congratulations, and thanks for sharing!
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.