Statistical programming, matrix languages, and more

Create Unique SAS data sets from matrices inside a SAS/IML DO loop

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 15
Accepted Solution

Create Unique SAS data sets from matrices inside a SAS/IML DO loop

I am trying to store unique matrices generated inside a PROC IML DO loop into corresponding unique SAS data sets.

 

I provide code below that is comprised by two parts.  Each part is followed by the corresponding comments ('*part 1;','*part 2;').

 

Part one generates a unique matrix with each iteration of the DO loop.  The matrix is called v and is dynamically labelled with each do loop.  So at the end of the two iterations, there will be two distinct matrices, one labelled "b1", the other "b2".

Part 1 works fine.  Part 2 is where I am having difficulty.

 

In Part 2, I want to store these two matrices labelled "b1" and "b2" into unique SAS data sets with distinct names.  That is, I would like to store matrix labelled "b1" into a SAS data set named work.b1 and matrix labelled "b2" into a SAS dataset named work.b2.

 

I've read Professor Wicklin's blogs which have gotten me close, but there appears to be an issue with my syntax in my CREATE and CLOSE statements in Part 2 of my code.

 

For those who might be interested, links to Professor Wicklin's blog posts that I reference follow:

 

https://blogs.sas.com/content/iml/2011/04/18/writing-data-from-a-matrix-to-a-sas-data-set.html

 

https://blogs.sas.com/content/iml/2013/07/29/read-data-sets-array-names.html

 

So here are my questions given what I've stated above:

 

1. How can I modify my Part 1 code so that I can have unique matrix names instead of unique matrix labels.  In other words, how can I have PROC IML create a matrix b1 and b2 instead of a matrix v  labelled "b1" and "b2" for iteration 1 and 2, respectively.

 

2. How can I modify my Part 2 code so that I can store the unique matrices created in Part 1 as unique SAS data sets.  Meaning, how can I store the matrix generated in each iteration into SAS data sets that each SAS data set has its own name -- so that they don't overwrite each other in the work library..

 

Hope some one can help me.

 

Thanks.

 

 

 

 

 

proc iml;

*part 1;

do a = 1 to 2;
names = "b" +strip(char(a,1));
b = j(3,3);
call randseed(1234);
call randgen(b,"Normal");
v = b;
call valset(names,v);
print v[l=names];

*part 2;

dsNames = {names};
create (dsNames[1]) from v;
append from v;
close (dsNames[1]);

end;

quit;


Accepted Solutions
Solution
‎02-23-2018 07:46 PM
SAS Super FREQ
Posts: 4,239

Re: Create Unique SAS data sets from matrices inside a SAS/IML DO loop

First, congratulations on being almost there. Your program just needs a small modification.

Here is the modification of your program:

proc iml;
b = j(3,3); 
call randseed(1234);
do a = 1 to 2; *part 1;
call randgen(b,"Normal"); *part 2; names = "b" +strip(char(a,1));
create (names) from b; append from b; close (names); end;

Notice that the (names) variable can be used directly on the CREATE statement. Also, there is no need to use VALSET to create a named matrix. You can reuse the matrix name (b) within each loop.

 

You didn't say what you are trying to accomplish, but often the next step is to analyze each of these data sets by using a SAS procedure (maybe PROC MEANS, CORR, or PRINCOMP.)  When you write multiple data sets with different names, it is hard to analyze them all. Most people will write a macro loop that iterates over the names of the data sets and calls a SAS procedure on each data set name.  This is inefficient, as shown in the article "Simulation in SAS: The slow way or the BY way."  

 

If you are heading in that direction, consider writing all samples into one data set and using an ID variable to indicate which observations correspond with each sample, as follows:

 

proc iml;
call randseed(1234);
varNames = "ID" || ("b1":"b3");
b = j(3,3);
ID = j(3,1,1);
M = ID || b; 
create Samples from M[colname=varNames];
*part 1;
do a = 1 to 2;
   call randgen(b,"Normal");
*part 2;
   M[,1] = a;   /* assign first column */
   M[,2:4] = b; /* assign columns 2,3,4 */
   append from M;
end;
close;
quit;

proc means data=Samples;
by ID;
run;

 

View solution in original post


All Replies
Solution
‎02-23-2018 07:46 PM
SAS Super FREQ
Posts: 4,239

Re: Create Unique SAS data sets from matrices inside a SAS/IML DO loop

First, congratulations on being almost there. Your program just needs a small modification.

Here is the modification of your program:

proc iml;
b = j(3,3); 
call randseed(1234);
do a = 1 to 2; *part 1;
call randgen(b,"Normal"); *part 2; names = "b" +strip(char(a,1));
create (names) from b; append from b; close (names); end;

Notice that the (names) variable can be used directly on the CREATE statement. Also, there is no need to use VALSET to create a named matrix. You can reuse the matrix name (b) within each loop.

 

You didn't say what you are trying to accomplish, but often the next step is to analyze each of these data sets by using a SAS procedure (maybe PROC MEANS, CORR, or PRINCOMP.)  When you write multiple data sets with different names, it is hard to analyze them all. Most people will write a macro loop that iterates over the names of the data sets and calls a SAS procedure on each data set name.  This is inefficient, as shown in the article "Simulation in SAS: The slow way or the BY way."  

 

If you are heading in that direction, consider writing all samples into one data set and using an ID variable to indicate which observations correspond with each sample, as follows:

 

proc iml;
call randseed(1234);
varNames = "ID" || ("b1":"b3");
b = j(3,3);
ID = j(3,1,1);
M = ID || b; 
create Samples from M[colname=varNames];
*part 1;
do a = 1 to 2;
   call randgen(b,"Normal");
*part 2;
   M[,1] = a;   /* assign first column */
   M[,2:4] = b; /* assign columns 2,3,4 */
   append from M;
end;
close;
quit;

proc means data=Samples;
by ID;
run;

 

Highlighted
Occasional Contributor
Posts: 15

Re: Create Unique SAS data sets from matrices inside a SAS/IML DO loop

Hi Professor Wicklin,

 

Thanks so much for answering my questions and anticipating my next steps!

 

Your response was very helpful and I am excited to apply your suggestions to the project I'm working on.

☑ This topic is solved.

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

Discussion stats
  • 2 replies
  • 285 views
  • 1 like
  • 2 in conversation