Hi,
I have a dataset with two columns like the following:
data temp;
input item count;
datalines;
a1 n1
a2 n2
a3 n3
...
ak nk
;
run;
Basically, {n1, n2, ...,n k} are the counts of {a1,... ak}. I would like to compute the number b= (n1*n2 + n1*n3+ ... +n1*nk) + (n2*n3 + n2*n4+...n2*nk) + ...+
(n_(k-1) *nk). Is there any efficient way to do it?
Thanks.
And you want to do this in IML ?
It appears this non-IML way is incorrect.
The straightforward way is efficient and simple to understand:
data temp;
input item $ count;
datalines;
a1 2
a2 4
a3 3
a5 2
a5 1
a6 5
;
proc iml;
use temp;
read all var "count" into n;
close;
k = nrow(n);
/* simplest way */
sum = 0;
do i = 1 to k-1;
sum = sum + n[i]*sum(n[(i+1):k]);
end;
print sum;
If by "efficient" you mean "vectorized," you can get rid of the DO loop by noting that the SUM() function inside the loop is computing the cumulative sums of the vector n in reverse order. Thus you could use the CUSUM function to compute the cumulative sums and then perform an inner product with n to get the sum:
/* use cumulative sums of the reverse of n */
m = n[ k:1 ]; /* reverse n */
cs = cusum(m); /* cumulative sums */
c = cs[k:1]; /* reverse the cumulative sums */
*print c; /* if you need to see the cumulative sums */
/* inner product of n and (reverse) cumulative sums */
sum = n[1:(k-1)]` * c[2:k];
print sum;
Hi Rick,
Very nice solution. Actually my goal is to use this sum inside of my code to do some additional computation, instead of just printing it. How do I send this sum to a macro variable to save it and do further computation from inside proc iml and then close proc iml to proceed outside of proc iml? Can I use %let statement inside proc iml or it has other interface to send this sum out to a macro variable? Thanks.
CALL SYMPUT("MyMacro", char(sum));
Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.