turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

Topic Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

05-30-2016 08:08 AM

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;
```

Accepted Solutions

Solution

05-30-2016
11:27 PM

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Jack2012

05-30-2016 10:55 AM

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.

All Replies

Solution

05-30-2016
11:27 PM

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Jack2012

05-30-2016 10:55 AM

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.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to IanWakeling

05-30-2016 10:17 PM

Dear Ian,
Very much appreciated for your creative idea. Yes, you are correct, this does work. However, if for a TRY with higher number of rows, like ten thousand, then b would be very huge, not sure there is any better solution to this.
Many thanks,
Jack

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to IanWakeling

05-30-2016 10:47 PM

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Jack2012

05-30-2016 10:27 PM

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;
```

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Ksharp

05-30-2016 10:54 PM

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Ksharp

05-30-2016 11:29 PM

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.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Jack2012

05-30-2016 11:34 PM

Never mind. I really don't care about it.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Ksharp

05-31-2016 03:42 AM - edited 05-31-2016 03:48 AM

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.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to IanWakeling

05-31-2016 11:03 PM

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.