2013-07-05 2 views
1

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

+0

Двойной amperstand на вкладке ... Я идиот. – Pane

+1

Блестящий! Отправьте свое решение в качестве ответа и примите его. Это определенно достаточно распространенная ошибка, которая стоит иметь в качестве решения в StackOverflow :) – Joe

ответ

2

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

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

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

1

Если у вас есть SAS/IML 12.1 (выпущено с 9.3m2), есть еще более простой способ. USE statement supports dereferencing data set names, так:

ds = "MyData"; 
use (ds); 

Кроме того, как я показываю в моей article on using the VALSET function, то 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; 
+0

Избавление от макроса было моей целью в какой-то момент. Я думаю, вы могли бы написать 'call valset (« Mat »+ strip (char (i)));' с вашим решением, чтобы сделать его более аккуратным. К сожалению, я все еще на 9.2. Насколько я понимаю, это решение не будет работать с этой версией? – Pane

Смежные вопросы