Сравнение числовых значений макроса - PullRequest
0 голосов
/ 09 января 2019

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

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 0.2
ERROR: The %TO value of the %DO I loop is invalid.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 0.05
ERROR: The %BY value of the %DO I loop is invalid.
ERROR: The macro FAIL will stop executing.

Мой код следующий:

%macro fail;
      %do i=0 %to 0.2 %by 0.05;
          data failcrs;
              set fail;
              if f_p>=input(&i, 8.) then output;
          run;
      %end;
%mend failcrs;

f_p - числовая переменная.

Что не так с моим кодом? Пожалуйста, помогите.

Большое спасибо!

Ответы [ 5 ]

0 голосов
/ 10 января 2019

Документация написана для чтения, простой поиск «SAS 9.4 Macro Do» должен объяснить все это - start, stop и by - целые числа - целые числа в том смысле, что любое выражение источника макроса на их месте вычисляется неявно или явно в целое число в нужное время.

Макрос, который вы кодировали, немного странный. Он сгенерирует несколько шагов данных, которые перезаписывают один и тот же набор данных. Возможно, вы захотите сконцентрироваться на том, чтобы сначала не писать код макроса, и переходите к нему, когда нужно будет представить повторяющийся шаблонный код. Написание хорошего макрокода означает, что вы должны подумать о том, «будет ли это генерировать соответствующий исходный код и какой побочный эффект будут у этих операторов макроса в их области разрешения»

% DO, итеративное утверждение

Синтаксис

% DO макро-переменная = start % TO stop <% BY <em>приращение >;

текстовые и макроязыковые операторы

% END;

Обязательные аргументы

макро-переменная

  • называет макрос-переменную или текстовое выражение, которое генерирует макрос имя переменной. Его значение действует как индекс, который определяет количество итераций цикла% DO. Если указана макропеременная поскольку индекс не существует, макропроцессор создает его в таблица локальных символов.

  • Вы можете изменить значение индексная переменная во время обработки. Например, используя условный обработка для установки значения индексной переменной после остановки значение при выполнении определенного условия завершает обработку цикла.

StartStop

  • указание целых чисел или выражений макросов, которые генерируют целые числа контролировать количество раз часть макроса между обрабатываются итеративные операторы% DO и% END.

  • Первый раз Группа% DO повторяется, макро-переменная равна start. Как обработка продолжается, значение макропеременной изменяется на величину увеличивать до тех пор, пока значение макропеременной выходит за пределы диапазона целые числа, включенные в начало и конец.

приращение

  • указывает целое число (кроме 0) или макрос-выражение, которое генерирует целое число для добавляется к значению индексной переменной в каждой итерации петля. По умолчанию приращение равно 1. Приращение оценивается до Первая итерация цикла. Поэтому вы не можете изменить его как цикл повторяется.

0 голосов
/ 10 января 2019

Условные тесты в коде макроса (%if, %until, %while и т. Д.) Используют функцию макроса %eval(), которая выполняет только целочисленную арифметику. Сюда входят приращения и тесты, выполненные в цикле% do-% to%.

Чтобы использовать арифметику с плавающей запятой, вам нужно использовать макрофункцию %sysvalf().

Вы можете кодировать свои собственные приращения в счетчике цикла.

%let i=0;
%do %while( %sysevalf( &I <= 0.2 ) );
   ...
   %let i=%sysevalf(&i + 0.05);
%end;

Или сделайте счетчик цикла целым числом и используйте другую макропеременную для хранения дроби.

%do j=0 %to 20 %by 5 ;
   %let i=%sysevalf(&j/100);
   ...
%end;
0 голосов
/ 10 января 2019

У вас есть пара вопросов. Макро-циклы лучше работают с целыми числами, но вместо этого простым обходным решением является цикл% DO% UNTIL.

  1. Имя в% MEND отличается от имени в% MACRO
  2. Недопустимые значения для цикла% DO% I.
  3. Неуникальное имя набора данных, что означает, что выходные данные перезаписываются.

    *fake data to work with;  
    data fail;
        do f_p=0 to 0.2 by 0.01;
            output;
        end;
    run;
    
    %macro fail;
        %let i=0;
          %do %until(&i = 0.2); /*2*/
              data failcrs_%sysevalf(&i*100); /*3*/
                  set fail;
                  if f_p>=&i then output;
              run;
              %let i = %sysevalf(&i + 0.05);
          %end;
    %mend fail; /*3*/
    
    *test macro;
    %fail;
    

Цифры в комментариях соответствуют выявленным проблемам.

0 голосов
/ 10 января 2019
%macro fail;
        %let i=0;
        %do %until(&i = 0.2);
            data failcrs; 
                set crse_grade_dist_fail;
                if f_p>=&i then output;
                run;

        proc sql;
            create table count_failclass as
            select strm, count(class_nbr) as numfclass_%sysevalf(&i*100)
            from failcrs
            group by strm;
        quit;

        proc sql;
            create table failfaculty as
            select strm, instructor_id, instructor, count(class_nbr) as numfclass
            from failcrs
            group by strm, instructor_id, instructor;
        quit;

        proc sql;
            create table count_failfaculty as
            select strm, count(instructor) as numffaculty_%sysevalf(&i*100)
            from failfaculty
        group by strm;
        quit;

        data count_class_faculty;
            set count_class_faculty;
            set count_failclass;
            set count_failfaculty;
        run;

        %let i = %sysevalf(&i + 0.05);
    %end;
%mend fail;

Хорошо, что мои данные не имеют f_p = 0, все они больше нуля. Потому что я хочу считать только неудачные курсы.

0 голосов
/ 10 января 2019

Попробуйте использовать best32. Но почему вы хотите выполнить цикл, когда ваш набор данных перезаписывается для каждого цикла. Пожалуйста, проверьте журнал для каждого из шагов ниже. Как у @Reeza в комментариях объясняет ниже, вы даже не вводите заявление Комплектация mprint;

   /* do this*/
    %macro fail;
   %let i =15;
    data failcrs;
          set sashelp.class;

          if age lt input(&i, best32.)  then output;
      run;
   %mend fail;

  %fail

   /* dataset overwritten every time to finally pick up 15 as value check in the log*/
   %macro fail1;
   %do i = 1 %to 15;
    data failcrs1;
          set sashelp.class;

          if age lt input(i, best32.) then output;
      run;
  %end;
 %mend fail1;

%fail1
...