Do-loop в SAS-IML

Я хочу использовать макрос do цикла внутри proc iml так:

%Let Tab1=FirstTable;
%Let Tab2=SecondTable;
%Let Tab3=ThirdTable;

*&Tab1-3 have been initialised as sas datasets;   

proc iml;

* This works;

use &Tab1;
read all into Mat3;
print Mat3;


* This doesn't work;

%Macro Define_mx;
    %do i=1 %to 2;
    use &Tab&i;
    read all into Mat&i ;
   %end;
  %Mend Define_mx;
%Define_mx;

*The two matrixes have not been initialised;

print Mat1;
print Mat2;
quit;

На самом деле мне придется инициализировать около 50 матриц, поэтому необходим цикл do. Я не могу понять, почему цикл не может видеть &Tab&i как макро переменную. Я также попробовал обходной путь с обычным (не макро) циклом do с использованием substr для объединения имен переменных, но он также не работал. Что мне здесь не хватает?

2 ответа

Решение

Итак, макрос должен быть:

%Macro Define_mx;
 %do i=1 %to 2;
   use &&Tab&i;
   read all into Mat&i ;
 %end;
 %Mend Define_mx;
%Define_mx;

Второй амперстенд на Tab необходим, так как без него макропроцессор попытался бы интерпретировать &Tab как макропеременную (которая не существует). Таким образом, при попытке объединить несколько макропеременных для создания новой, используйте &&.

Если у вас SAS/IML 12.1 (выпущен с 9,3 м2), есть еще более простой способ. Оператор USE поддерживает разыменование имен наборов данных, например:

ds = "MyData";
use (ds);

Кроме того, как я покажу в своей статье об использовании функции VALSET, язык SAS / IML поддерживает функцию VALSET, которая может динамически создавать матрицы с именами Mat1, Mat2 и так далее. Вы можете комбинировать эти функции, чтобы полностью исключить макросы:

data a b c;                 /* create sample data sets */
x=1;y=2; output;
x=2;y=3; output;
run;

proc iml;
dsnames = {a b c};          /* names of data sets */
do i = 1 to ncol(dsnames);
   use (dsnames[i]);        /* open each data set */
   read all into X;
   close (dsname);
   MatName = "Mat"+strip(char(i)); /* create Mat1, Mat2,... */
   call valset(MatName, X);        /* assign values from data set */
end;
show names;
Другие вопросы по тегам