SAS использует итерирующую переменную с циклом do

У меня есть образец набора данных, и я пытаюсь создать новый набор данных из каждого наблюдения (записи) с помощью цикла выполнения.

вот пример кода:

data tst;
input a b;
datalines;
1 2
2 3
;
run;

data ds1 ds2;
set tst 
/*point = point nobs = Nobs*/
;
do i=1 to 2;
    call symput("i",i);
    %put &=i;
    if _n_ then output ds&i.;
end;
run;

Я смущен, почему &i. не разрешается правильно. Похоже, что в журнале перед ним много места. Я попытался использовать функцию сжатия для ds&i., и это не сработало. Я знаю, что мог бы использовать макрос и сделать это без вызова symput(), но мне интересно, в чем проблема?

Идеальный выход:

DS1:
a b 1 2

DS2:
a b 2 3


person DukeLuke    schedule 22.10.2019    source источник
comment
блоги .sas.com/content/sasdummy/2015/01/26/ или прочтите этот пост с еще двумя ссылками на обходные пути: communities.sas.com/t5/SAS-Programming/   -  person Reeza    schedule 23.10.2019


Ответы (2)


Это известное поведение. Выдержка из руководства по вызову symput:

Проблема при попытке сослаться на присвоенное SYMPUT значение до того, как оно станет доступным

Одной из наиболее распространенных проблем при использовании SYMPUT является попытка сослаться на значение макропеременной, присвоенное SYMPUT до того, как эта переменная будет создана. Ошибка обычно возникает из-за того, что оператор, ссылающийся на переменную макроса, компилируется до выполнения оператора CALL SYMPUT, который присваивает значение переменной. Самый важный факт, который следует помнить при использовании SYMPUT, заключается в том, что он присваивает значение переменной макроса во время выполнения программы. Ссылки на макропеременные разрешаются во время компиляции шага, глобального оператора, используемого вне шага, или программы SCL. Как результат:

Вы не можете использовать ссылку макропеременной для получения значения макропеременной в той же программе (или шаге), в которой SYMPUT создает эту макропеременную и присваивает ей значение.

Вы должны указать оператор границы шага, чтобы принудительно выполнить шаг DATA перед ссылкой на значение в глобальном операторе, следующем за программой (например, в операторе TITLE). Границей может быть оператор RUN или другой оператор DATA или PROC.

person SAS2Python    schedule 22.10.2019
comment
Используйте SYMGET(), чтобы использовать переменную в том же шаге данных. Это было обновлено. - person Reeza; 23.10.2019

Это происходит из-за того, что макропеременная не может быть использована на шаге данных, где она была инициализирована. Поэтому я думаю, что вы должны использовать макрос (и исправить оператор if, в примере сделано так, как я думаю):

data tst;
input a b;
datalines;
1 2
2 3
;
run;

%macro output(); %macro d;%mend d;
   data ds1 ds2;
   set tst 
   /*point = point nobs = Nobs*/
   ;
   %do i=1 %to 2;
       if mod(_n_,&i)=0 then output ds&i.;
       /*if _n_=&i then output ds&i.;*/
   %end;
   run;
%mend output;

%output();

набор данных tst:

+---+---+
| a | b |
+---+---+
| 1 | 2 |
| 2 | 3 |
+---+---+

набор данных ds1:

+---+---+
| a | b |
+---+---+
| 1 | 2 |
+---+---+

набор данных ds2:

+---+---+
| a | b |
+---+---+
| 2 | 3 |
+---+---+
person Alexey Sigida    schedule 23.10.2019