Hi, All,
Suppose I simulate a dataset via do loop and get a matrix with below code.
My question is: How could I get the sum of x, by i and j values?
Exactly speaking, I want to this:
denote sum as a coloumn vector with dimention is 12*1, with sum[1]=sum(x1:x3) given i=j=1; sum[2]=sum(x2:x3) given i=1 and j=2;
.....sum[10]=sum(x10:x12) given i=4 and j=1; sum[11]=sum(x11:x12) given i=4 and j=2; sum[12]=sum(x12) given i=4 and j=3;
How should I program via PROC IML to reach such aim? Much appreciated for your help to a fresh to IML procedure.
data test;
do i=1 to 4;
do j=1 to 3;
call streaminit(i*j);
x=rand("normal");
output;
end;
end;
run;
PROC IML;
USE test var {i j x};
read all var {i j x} into TRY;
quit;
One possibility might be to construct a matrix of zeros and ones (b) that gets the necessary sums by matrix multiplication.
a = {1 1 1, 0 1 1, 0 0 1};
b = block(a,a,a,a);
s = b * TRY[ ,3];
print b [format=1.0] s;
Here the BLOCK function places 4 copies of the 3x3 matrix 'a' on the diagonal of a 12x12 matrix.
One possibility might be to construct a matrix of zeros and ones (b) that gets the necessary sums by matrix multiplication.
a = {1 1 1, 0 1 1, 0 0 1};
b = block(a,a,a,a);
s = b * TRY[ ,3];
print b [format=1.0] s;
Here the BLOCK function places 4 copies of the 3x3 matrix 'a' on the diagonal of a 12x12 matrix.
Dear Ian,
Just checked the function of BLOCK in SAS web and found for the higher order of TRY, this method is not workable. I think I should go back to consider to the DATA step.
http://support.sas.com/documentation/cdl/en/imlug/59656/HTML/default/viewer.htm#langref_sect32.htm
Many thanks still for your creative idea.
Jack
Your logic is not clear for me .
Why not use Data Step ? since it is not about VECTOR operation .
data test;
do i=1 to 4;
do j=1 to 3;
call streaminit(i*j);
x=rand("normal");
output;
end;
end;
run;
PROC IML;
use test nobs nobs;
read all var {i j x} into TRY;
close;
start=1:nobs;
end=start+repeat({2 1 0},1,int(nobs/3));
sum=j(nobs,1,.);
do i=1 to nobs;
sum[i]=sum(try[start[i]:end[i],3]);
end;
print try sum;
quit;
Dear KSharp,
I am really appreciated for your reply at very late night for you. Sorry for unclear logic of my question, but really I have to day, you really produced the right result I am hunting for.
And I fully agree with you maybe should use data step, as I am not working on the vector but block.
Many thanks.
Jack
It seems I can't set two solutions, but I have to admit I prefer yours as it is easy to expand for simulation. Thanks.
Hi Jack,
I did not realise that you wanted to scale it to thousands of observations, so the 15 matrix limit on the BLOCK function is clearly a problem, and anyway you would not want to create and multiply zero/one matrices that large. It is possible to vectorize the problem within IML by realising that what you want is not far away from the cumulative sum of the data vector in reverse.
n = 12;
m = 3;
c = cusum(TRY[n:1,3])[n:1];
s = c - (c[do(m+1, n-m+1, m)]//0) @ j(m, 1);
print try c s;
Where n is the total number of obsertations and m the sub-group size.
Ian.
Dear Ian,
Millionn thanks to your further code, yes, I think your logic is quite the same as Keshan's. Realy thank you both.
Jack.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9.
Lock in the best rate now before the price increases on April 1.