SAS if оператор в цикле do - PullRequest
       11

SAS if оператор в цикле do

0 голосов
/ 06 ноября 2018

Привет, я пытаюсь написать макро функцию с циклом do и оператором if. Я думаю, что перепутал цикл if-then do и do, и я не могу понять проблему. У меня есть таблица информации о детях, которая содержит столбцы, такие как возраст, пол, спорт, инструменты и т. Д.

Мой оригинальный код, который работает, выглядит следующим образом:

data old;
   set new;
   if sports in ("football","basketball") and age <=7 then type =1;
      else if sports='swimming' then type=2;
   if special_kid=. then do;
     if piano ^=. and piano_1 ^=. then do; talent_type=1; type_name=piano_1; end;
     if violin ^=. and violin_1 ^=. then do; talent_type=1; type_name=violin_1; end;
   end;
 run;

У меня есть набор инструментов, которые я хочу отредактировать типом и именем. Я хочу написать цикл для автоматического выполнения этого, но я не уверен, почему приведенные ниже коды не работают.

%let instrm = piano violin;
%macro my_func;
   data old;
   set new;
   %if sports in ("football","basketball") and age <=7 %then type =1;
      %else %if sports='swimming' %then type=2;
   %do %while (special_kid=.);
      %do i % to sysfunc(countw(&instrm));
          %let word = %scan(&name, &i);
          %if &word ^=. and ^word._1 ^=. %then %do;
          talent_type=1; type_name=&word._1;
          %end;
     %end;
  %end;
run;
%mend;

Он продолжает давать мне ошибки

 ERROR: An unexpected semicolon occurred in the %DO statement.
 ERROR: A dummy macro will be compiled.

Может кто-нибудь ответить на мой вопрос? Спасибо!

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

В вашем коде было несколько настроек, я сделал некоторые изменения. Кроме того, когда мы используем%, если мы всегда используем макропеременные. В противном случае мы можем использовать операторы if только с обычными переменными набора данных.

%let instrm = piano violin;
%macro my_func;
 data old;
   set new;
   if sports in ("football","basketball") and age <=7 then type =1;
      else if sports='swimming' then type=2;
   if missing(special_kid) then do;
      %do i=1 %to %sysfunc(countw(&instrm));
          %let word = %scan(&instrm, &i);
          %If &word ^=. and &word._1 ^=. %then %do;
          talent_type=1; type_name=&word._1;
          %end;
      %end;
  end;
run;
%mend my_func;
0 голосов
/ 07 ноября 2018

Макропеременная instrm действительно является значением, содержащим список имен переменных, разделенных пробелами. Возможно, вам лучше абстрагироваться от конкретной роли использования переменной и перейти к более общему имени параметра vars. Кроме того, вместо того, чтобы полагаться на макропеременную, определенную в глобальной или охватывающей области, передайте список во время вызова. Вы правы в том, что разделенный пробелами список может быть перебран в макросе с циклом %do с верхним пределом, равным countw числу «слов» в списке - ваш синтаксис немного отклонен.

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

Ваш исходный код может быть ошибочным, поскольку вы оцениваете (в одной строке) несколько специальных дочерних переменных и выполняете присвоение значений одним и тем же 2 переменным (talent_type и type_name) и, таким образом, можете перезаписать ранее назначенное значение. Иногда такие оценки и присвоения OUTPUT для отдельных строк.

%macro my_skill_classifier(data=, out=, special_vars=, special_type=);
   %local i var;

   data &out;
   set &data;

   if sports in ("football","basketball") and age <=7 then type = 1;
   else
   if sports='swimming' then type=2;

   * what happens to football/baskeball > 7yr ?;

   if missing(special_kid) then do;
      %do i = 1 %to sysfunc(countw(&special_vars));
        %let var = %scan(&special_vars, &i);

        * regular data step code with macro resolutions sprinkled in;
        if &var ^=. and var._1 ^=. then do; 
          talent_type = &special_type;
          type_name = &var._1;
          * maybe you really mean type_name = "&var._1";
        end;
      %end; %* end loop over special_vars list;
    end;
  run;
%mend;

%my_skill_classifier(data=new, out=old, special_vars=piano violin, special_type=1)

Короче говоря, убедитесь, что ваша методология формирования и оценки данных является надежной, прежде чем начинать макрокодирование. Если вы спросите себя Должен ли я это макрос? , будьте осторожны и ответьте нет. Будьте дружелюбны по отношению к сопровождающим и будущему, не усложняя вещи.

...