2016-08-25 2 views
0

Я работаю с SAS, и мне нужно создать некоторые макропеременные в цикле DO. Это часть моего кода:Как использовать макрокоманду && в SAS

%if &dsempty888=0 %then %do; 
    data _null_; 
    set freq_&&var&i; 
     if &&var&i=888888888 then do; 
      call symput("cont8_&&var&i",percent); 
     end; 
    run; 
%end; 
%if &dsempty888=1 %then %do; 
    %let cont8_&&var&i=0; 
%end; 

%if &dsempty999=0 %then %do; 
    data _null_; 
    set freq_&&var&i; 
     if &&var&i=999999999 then do; 
      call symput("cont9_&&var&i",percent); 
     end; 
    run; 
%end; 
%if &dsempty999=1 %then %do; 
    %let cont9_&&var&i=0; 
%end; 


%if &dsempty444=0 %then %do; 
    data _null_; 
    set freq_&&var&i; 
     if &&var&i=444444444 then do; 
      call symput("cont4_&&var&i",percent); 
     end; 
    run; 
%end; 
%if &dsempty444=1 %then %do; 
    %let cont4_&&var&i=0; 
%end; 

Этот код находится внутри другой DO цикл, который запускается из i=1 to &end. С этими моими переменными макросов cont4_&&var&icont8_&&var&icont9_&&var&i переименованы в ... но они становятся неиспользованными за пределами их цикла. Например, я попытался назвать их &&cont4_&&var&i. Но, очевидно, SAS не решает макрос. На практике внутри цикла создается макрос, но я не знаю, как их называть, когда мне нужно снаружи.

Как я могу исправить?

Заранее спасибо.

+0

также [этот вопрос] (http://stackoverflow.com/questions/24895197/resolving-multiple-ampersands- с макро-переменными) и [этот вопрос] (http://stackoverflow.com/questions/22903856/sas-macro-ampersand/22915555#22915555) для получения дополнительной информации о множественном амперсанде. – Joe

ответ

4

У вас здесь много проблем, поэтому давайте упростим это. Вот очень упрощенный пример. Это, к примеру, что-то делает:

%let var1 = age; 
%let var2 = height; 
%let var3 = weight; 

proc freq data=sashelp.class noprint; 
    tables age/out=freq_age; 
    tables height/out=freq_height; 
    tables weight/out=freq_weight; 
run; 


%macro get_freqs(var_count=); 
    %do i = 1 %to &var_count.; 
     data _null_; 
     set freq_&&var&i; 
     call symput("cont4_&&var&i",percent); 
     run; 
    %end; 
%mend get_freqs; 

%get_Freqs(var_count=3) 

Но теперь, если мы делаем

%put cont4_&&var&i; 

Конечно, это не работает, так как &i не имеет никакого значения. Поэтому вместо этого мы заменяем это, скажем, 1:

%put cont4_&&var1; 

Теперь мы получаем что-то. Но мы не получаем ничего полезного, не так ли, просто имя переменной. Но - по крайней мере, это что-то!

Теперь нам не нужен второй &, верно?

%put cont4_&var1; 

Но нам нужно & перед этим использовать макропеременную:

%put &cont4_&var1; 

Но теперь мы получаем предупреждение, CONT4_ not resolved. Хорошо, давайте добавим второй &, чтобы отложить разрешение переменной макроса до тех пор, пока не будет разрешено &var1.

%put &cont4_&var1; 

Ну, что помогло, теперь он говорит CONT4_AGE not resolved. Почему нет? Мы использовали call symput, чтобы определить это, правильно?

Проблема с осмотром. call symput, вероятно, скопировал его локально, то есть он был определен в макросе, но не вне макроса. Для этого мы используем call symputx и придаем ему глобальный масштаб.

%macro get_freqs(var_count=); 
    %do i = 1 %to &var_count.; 
     data _null_; 
     set freq_&&var&i; 
     call symputx("cont4_&&var&i",percent,'g'); 
     run; 
    %end; 
%mend get_freqs; 

Это говорит SAS, что я хочу &cont4_age быть определен вне макроса. В противном случае он будет доступен только локально - внутри макроса - и будет очищен.

Теперь это работает:

%put &&cont4_&var1; 

Но если вы хотите, чтобы перебрать &i снова, это немного сложнее.Это потому, что вам нужно несколько раз откладывать эти амперсанды и допускать несколько проходов.

Вот что работает:

%macro iterate_i(var_count=); 
    %do i = 1 %to &var_count.; 
    %put &&&&cont4_&&var&i.; 
    %end; 
%mend iterate_i; 

%iterate_i(var_count=3); 

Зачем нам нужны четыре& сек? Ну, нам нужно добраться до &&cont4_&var1, правильно? Это происходит в первый проход. Вот три прохода:

&&&&cont4_&&var&i ->&&cont4_&var1 ->&cont4_age -> 5,26 ...

Каждый проход, происходит следующее:

  • && ->& (и сохранить для следующего прохода)
  • & -> разрешить макропеременная

Итак, вот как вы будете перебирать их. Вы, конечно, можете явно указать на любом уровне в макропеременную - так что все эти работы:

%let i=1; 
%put &&&&cont4_&&var&i; 
%put &&cont4_&var1; 
%put &cont4_age; 
Смежные вопросы