Do-loop в SAS-IML

Я хочу использовать макрос do loop внутри 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 матриц, поэтому необходим цикл выполнения. Я не могу понять, почему цикл не видит &Tab&i как переменную макроса. Я также пробовал обходной путь с обычным (не макрокомандным) циклом выполнения, используя substr для объединения имен переменных, но это тоже не сработало. Что мне здесь не хватает?


person Pane    schedule 05.07.2013    source источник
comment
Двойной амперстенд на Табе... Я идиот.   -  person Pane    schedule 05.07.2013
comment
Великолепно! Пожалуйста, отправьте свое решение в качестве ответа и примите его. Это определенно достаточно распространенная ошибка, которую стоит иметь в качестве решения в StackOverflow :)   -  person Joe    schedule 05.07.2013


Ответы (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 как переменную макроса (которой не существует). Таким образом, при попытке объединить несколько макропеременных для создания новой используйте &&.

person Pane    schedule 06.07.2013

Если у вас 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;
person Rick    schedule 07.07.2013
comment
Избавление от макроса тоже было моей целью в какой-то момент. Я думаю, вы могли бы написать call valset("Mat"+strip(char(i))); с вашим решением, чтобы сделать его более аккуратным. К сожалению, я все еще на 9.2. Как я понимаю, это решение не будет работать с этой версией? - person Pane; 08.07.2013