The || operator is not what you want in the IML code (also not what you want in your data step example either but let's ignore that). The + operator is what is used to append strings. This was discussed in the blog post from Rick about building a string with names.
proc iml;
use a;
read all var {x} into a;
close a;
print a;
do i=1 to 3;
name='a'+strip(putn(a[i],'5.'));
call execute(name+'=2;');
call execute('print '+name+';');
end;
quit;
@Tom wrote:
The || operator is not what you want in the IML code (also not what you want in your data step example either but let's ignore that).
No, that's exactly what I want. The "||" operator works perfectly in CALL EXECUTE routine of the DATA step. Try run the codes I provided a few hours ago and verify that this does generate datasets named a1, a2, a3, ..., a35. It is both relatively simple and efficient. So I wish to go on using it in IML. That is why I originally mentioned it in my post and repetitively referred to it in my various replies.
As for your codes provided... Yes, it does solve my problem with the help of string functions. I really appreciate your help. But I still grumble about the lack of simpler codes like the CALL EXECUTE code I composed above.
Note that the CALL EXECUTE() actually works better in PROC IML than it does in a data step. At least when using it to generate PROC IML statements. That is because the generated code is run immediately rather than being stacked up to execute later. When using CALL EXECUTE() in a data step the code generated does not run until the data step used to generate it finishes.
The || operator in the data step language is the STRING concatenation operator. Your code is concatenating strings with numbers. That will require the data step to convert the number into a string. When the data step does this it uses the BEST12. format for the number. In your example code
call execute ('data a'||x||'=2;run;');
that will cause it to generated invalid SAS code like:
data a 1=2; run;
You should either use the PUT() function, or the PUTN() function like the one that PROC IML will require, to first convert the number into a string.
Or use the new CAT... series of functions that SAS added recently. Those will automatically remove the leading spaces when they autoconvert numbers.
So perhaps something like:
call execute(catx('data',cats('a',x),';set a; where x=',x,';run;'));
Which will generate a data steps like these to run after the current data step finishes.
data a1 ;set a; where x=1 ;run;
data a2 ;set a; where x=2 ;run;
data a3 ;set a; where x=3 ;run;
Thank you for your further explanation.
@Tom wrote:
Note that the CALL EXECUTE() actually works better in PROC IML than it does in a data step. At least when using it to generate PROC IML statements. That is because the generated code is run immediately rather than being stacked up to execute later. When using CALL EXECUTE() in a data step the code generated does not run until the data step used to generate it finishes.
The || operator in the data step language is the STRING concatenation operator. Your code is concatenating strings with numbers. That will require the data step to convert the number into a string. When the data step does this it uses the BEST12. format for the number. In your example code
call execute ('data a'||x||'=2;run;');
that will cause it to generated invalid SAS code like:
data a 1=2; run;
You should either use the PUT() function, or the PUTN() function like the one that PROC IML will require, to first convert the number into a string.
Or use the new CAT... series of functions that SAS added recently. Those will automatically remove the leading spaces when they autoconvert numbers.
So perhaps something like:
call execute(catx('data',cats('a',x),';set a; where x=',x,';run;'));
Which will generate a data steps like these to run after the current data step finishes.
data a1 ;set a; where x=1 ;run; data a2 ;set a; where x=2 ;run; data a3 ;set a; where x=3 ;run;
Yes, I found myself wrong on this code. An error is reported when I ran my code. The correct way to do this is to transform the numerical variable represented by x into character ones. In addition, the "=2" is incorrect. The correct code should be like this:
data _null_;
set a;
call execute ('data a'||cats(x)||';a=2;run;');
run;
Other string functions like the ones you used can also be employed.
@Season wrote:
Now that my first question is resolved, I turn to the second. I am not sure of what your sentence of "I am not sure why when they added the ability to use name lists to reference datasets they did not also add a similar feature to the IML commands that reference matrixes." means. I am not a native English speaker. Please forgive me for my lack of fluency in English to understand this sentence.
SAS has had the ability to use a hyphen to generate a list of variables names with a common prefix and a sequence of numeric suffixes in data step code for a long time.
data want;
set have;
array x var1-var10;
....
But this similar syntax that allows you make a list of dataset names was only added very recently to the SAS language.
data want;
set a1-a3;
run;
So you are asking that they make a similar enhancement to the IML language to allow the LOAD statement to use a similar syntax for specifying a list of matrix names.
Thank you for your further explanation, including the history of change in SAS arguments! I previously proposed several suggestions on improving SAS that I thought was necessary in the SAS Product Suggestions block of SAS Community. You can see from my personal profile page that I have the "Now that's an idea" badge. However, none of the suggestions were adopted, making me a bit frustrated. So I may not propose my suggestion this time. But thank you for suggesting that I propose a suggestion anyway!
When I analyze lots of coviarance matrixes I use method in Rick's blog
https://blogs.sas.com/content/iml/2015/02/09/array-of-matrices.html
Reason Rick says don't need many matrixes with different names is because you cna write loop and reuse same matrix as shown at end of blog. Just store each result as flat row in result matrix.
I also like example of simulation (like jackknife) in this blog https://blogs.sas.com/content/iml/2012/05/16/the-curious-case-of-random-eigenvalues.html Rick makes matrix in loop and stores it (or related result like eigenvalsi) flat in row. That is a good way. Then easy no trouble to store and load results. The ith row holds ith matrix.
ALso, I like to store results matrix as sas datset instead of use STORE command. Datset more flexible and cna be grphed and used in other procudures. If use STORE command, only is good inside IML.
Thank you for taking time to read and learn about my problems and sharing your experience. I generated matrices (in fact, vectors in my case) with different names because they actually came from independent loops enclosed in a macro written by me. Assigning them independently with different names and a common prefix makes me easier to find mistakes if there is any. I have the habit of randomly choosing entries of a matrix and match them to previous SAS procedure outputs to see if there is any programming error. As the matrix becomes larger, it is difficult for you to find entries in the middle of the matrix and you may only focus on the very outer entries of the big matrix.
As for the debate of dataset vs. matrices, I chose matrices because the task I was about to perform right after I compute the covariance matrix is to calculate its eigenvalues. I agree that if the task varies, storing matrices as datasets might be a good alternative.
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!