2013-03-22 5 views
6

Я искал в то время как эквивалент для в цикле (например, в Python или R) в SAS 9.3 Macro Language. DO loop кажется, что это решение, но не работает точно так, как я хочу. Я основал способ сделать это на шаге данных с помощью цикла DO, но он не работает с языком макросов. Например, на этапе обработки данных, этот код работает:«Ибо в» эквивалентной петли в SAS 9.3

DATA _NULL_; 
    DO i = 1,3,5,9; 
    PUT i; 
    END; 
RUN; 

А потом журнал оперативно, как и ожидалось:

1 
3 
5 
9 

Когда я пытаюсь сделать то же самое с % DO цикл в Макро, у меня есть ошибка.

%MACRO test(); 
    %DO i = 1,2,4,9 ; 
    %PUT i = &i; 
    %END; 
%MEND; 

%test(); 

Журнал promp эти сообщения:

ERROR: Expected %TO not found in %DO statement. 
ERROR: A dummy macro will be compiled 

Я совершенно новое в SAS и StackOverflow, так что я надеюсь, что мой вопрос не слишком глуп. Это так просто сделать в Python и R, тогда у него должен быть простой способ сделать это в SAS.

Спасибо за помощь - J. Muller

ответ

6

Ближайший я когда-либо сталкивался с этой моделью в SAS макроязыке это:

%MACRO test(); 

%let j=1; 
%let vals=1 2 4 9; 
%do %while(%scan(&vals,&j) ne); 
    %let i=%scan(&vals, &j); 

    %put &i; 

    %let j=%eval(&j+1); 
%end; 
%MEND; 

%test(); 

(Внимание: проверялся, как я уже не имею установок SAS я могу проверить это на.)

+0

Я пробовал, и он отлично работает. Это не так просто, как синтаксис Python или R, но он хорошо работает с списком символов. Благодаря! – jomuller

4

Вы, конечно, можете обойти это следующим образом:

options mindelimiter=,; 
options minoperator; 
%MACRO test(); 
    %DO i = 1 %to 9 ; 
    %if &i in (1,2,4,9) %then %do; 
    %PUT i = &i; 
    %END; 
    %end; 
%MEND; 

%test(); 

Однако, я думаю, что вы можете обычно избежать такого рода вызов, выполнив макрос несколько раз, а чем попытка управления петлей внутри макроса. Например, представьте себе набор данных и макрос:

data have; 
input x; 
datalines; 
1 
2 
4 
9 
;;;; 
run; 

%macro test(x); 
%put &x; 
%mend test; 

Теперь вы хотите позвонить% тест() один раз для каждого значения в этом списке. Хорошо, легко сделать.

proc sql; 
select cats('%test(',x,')') into :testcall separated by ' ' from have; 
quit; 

&testcall; 

Это работает точно так же, как ваш% сделать в цикле, за исключением того, что это данные ведомых, то есть, если вы хотите изменить вызовы, просто измените набор данных (или если ваши данные изменения, то вызов автоматически меняется!) , В целом, SAS более эффективен, когда он предназначен для программирования на основе данных, а не как полностью написанный код.

+0

Я использовал что-то похожее для числовых списков, но – jomuller

+1

Да, если вы хотите делать списки символов, вам нужно отсканировать список, как в примере Саймона. Я хотел бы отметить, что макрос SAS не является полностью полноценным языком - не ожидайте, что это будет. Большинство вещей можно сделать в базе SAS, не делая серьезного программирования на макроязыке, не избегая повторного кода. Пример добавлен в ответ. – Joe

+0

(конец моего предложения, извините, техническая проблема) ... он не работает для списка персонажей, я считаю. – jomuller

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