Как сделать цикл DO в SAS

Я новичок в SAS, и у меня проблемы с Do Loops. Ниже приведен фрагмент кода.

DATA _NULL_;
set testing;
    do i=_N_ to 4;
        call symputx(NAME,"E&_N_");
    end;
%PUT =&E&_N_; 
run;

Я ожидаю, что он выведет что-то ниже:

E1 = A
E2 = B 
E3 = C
E4 = D 

Однако я не могу заставить его работать. Любые идеи, что я делаю неправильно? Спасибо за помощь.


person Lonewolf    schedule 01.06.2017    source источник
comment
Что находится в вашем наборе данных TESTING?   -  person Quentin    schedule 02.06.2017
comment
набор данных содержит один столбец и 4 наблюдения (т.е. A, B, C, D)   -  person Lonewolf    schedule 02.06.2017
comment
И имя переменной ИМЯ?   -  person Quentin    schedule 02.06.2017
comment
Да, NAME — это переменная   -  person Lonewolf    schedule 02.06.2017


Ответы (1)


Сосредоточившись сначала на проблеме зацикливания, важно знать, что сам шаг DATA является циклом.

Данные образца данных:

data have;
  input name $1;
  cards;
A
B
C
D
;
run;

Если вы кодируете:

data _null_;
  set have;
run;

вы закодировали цикл, и цикл шага данных будет повторяться пять раз (а не четыре). На первой итерации оператор SET читает первую запись, на второй итерации он читает вторую запись, ... на пятой итерации оператор SET пытается прочитать пятую запись, но достигает конца файла и шага DATA останавливается. Самый простой способ увидеть эту итерацию — добавить операторы PUT:

46   data _null_;
47     put "top of loop " _n_= ;
48     set have;
49     put "bottom of loop " _n_= name= /;
50   run;

top of loop _N_=1
bottom of loop _N_=1 name=A

top of loop _N_=2
bottom of loop _N_=2 name=B

top of loop _N_=3
bottom of loop _N_=3 name=C

top of loop _N_=4
bottom of loop _N_=4 name=D

top of loop _N_=5
NOTE: There were 4 observations read from the data set WORK.HAVE.

Иногда полезно использовать явный цикл DO для чтения данных, а не полагаться на неявный цикл do. Неясно, будет ли это полезно в этом случае, но вы можете сделать это так:

52   data _null_;
53     do _n_=1 to 4;
54       put "top of loop " _n_= ;
55       set have;
56       put "bottom of loop " _n_= name= /;
57     end;
58   run;

top of loop _N_=1
bottom of loop _N_=1 name=A

top of loop _N_=2
bottom of loop _N_=2 name=B

top of loop _N_=3
bottom of loop _N_=3 name=C

top of loop _N_=4
bottom of loop _N_=4 name=D

top of loop _N_=1
NOTE: There were 4 observations read from the data set WORK.HAVE.

В этом случае все еще существует неявный пошаговый цикл DATA. Но на первой итерации неявного пошагового цикла DATA вы выполняете оператор SET четыре раза внутри явного цикла DO, читая все четыре записи. На второй итерации цикла шага DATA оператор SET пытается прочитать пятую запись и достигает конца файла, поэтому шаг DATA завершается.

Понимание неявного зацикливания шага DATA важно для начинающих программистов SAS. Большинство людей рекомендуют начинающим программистам ИЗБЕГАТЬ изучения языка макросов, потому что это другой язык, чем язык шага DATA. Поскольку язык макросов (обычно) используется для создания кода языка SAS, вам необходимо хорошо понимать язык SAS, прежде чем изучать язык макросов.

Тем не менее, если вашей целью является создание четырех макропеременных с именами E1 E2 E3 E4, которые будут разрешаться в значения A B C D соответственно, вы можете сделать это с помощью CALL SYMPUTX. Первый аргумент CALL SYMPUTX — это имя создаваемой макропеременной, а второй аргумент — это значение, которое будет присвоено этой макропеременной. Итак, вы можете сделать это так:

data _null_;
  set have;
  call symputx(cats("E",_N_),Name);
run;                             

%put E1=&E1 E2=&E2 E3=&E3 E4=&E4;

При этом используется функция CATS() для вычисления имени генерируемой макропеременной (буква "E" в сочетании со значением N) и присваивается значение переменной шага DATA ИМЯ к макропеременной. Существуют и другие способы создания таких списков макропеременных (они же массивы макропеременных). Важно отметить, что оператор %PUT стоит после оператора RUN. Это связано с тем, что оператор макроязыка %PUT не является частью языка шага DATA.

person Quentin    schedule 02.06.2017
comment
Большое спасибо! - person Lonewolf; 03.06.2017