SAS PROC SQL - вычислить столбец, используя значение, возвращаемое из макропрограммы - PullRequest
3 голосов
/ 12 марта 2019

Я хотел бы автоматизировать следующий расчет даты: добавить (или вычесть) X месяцев к данной числовой переменной, которая представляет дату в форме ГГГГММ, т.е. 201901 означает январь 2019 года. Пример: 201901 + 13 месяцев = 202002

Следующий макрос возвращает желаемое значение (& id_mes_n)

%macro suma_meses(id_mes_ini, n_meses);

%let anio_ini = %sysfunc(floor(&id_mes_ini/100)); /*get year*/
%let mes_ini  = %sysfunc(mod  (&id_mes_ini,100)); /*get month*/
%let aux      = %eval(12*&anio_ini + &mes_ini + &n_meses);

%let anio_n   = %sysfunc(floor(&aux/12)); /*calculate new year*/
%let mes_n    = %sysfunc(mod  (&aux,12)); /*calculate new month*/

%if &mes_n = 0 %then %do;                 /*correction for month 12*/
    %let id_mes_n = %eval(100*(&anio_n-1)+ 12);
%end;
%else %do;
    %let id_mes_n = %eval(100*&anio_n + &mes_n);
%end;

&id_mes_n /*returned value*/

%mend;

%suma_meses(201901, 13) /*returns 202002*/

Я хотел бы использовать макрос внутри PROC SQL следующим образом:

PROC SQL;
CREATE TABLE want AS 
SELECT T1.*, %suma_meses(T1.old_date, T1.x_months) AS new_date
FROM have T1
WHERE %suma_meses(T1.old_date, T1.x_months) > 201801 ;
QUIT;

Может ли это бытьсделанный?Поскольку этот тип вычислений является очень повторяющейся задачей для людей в моей области (мы не являемся администраторами, инженерами и т. Д.), Идея состоит в том, чтобы поделиться макросом с другими пользователями, чтобы упростил синтаксис .Другими словами, мы хотим сделать код более читабельным, избежать проблем с копированием-вставкой и освободить неопытных пользователей от серьезных ошибок вычислений XD (особенно, когда задействованы подзапросы, а X отрицателен).Такой макрос сделает нашу жизнь проще.

Ответы [ 2 ]

1 голос
/ 12 марта 2019

Звучит так, будто вы пытаетесь рассматривать числа, например 201 801, как если бы они представляли первый месяц в 2018 году, а затем добавляли число месяцев и генерировали число, используя тот же «стиль».

Если выесли вы хотите сделать это с помощью цифровых строк в коде макроса, вы можете создать макрос следующим образом:

%macro add_months_macro(date,months);
%sysfunc(intnx(month,%sysfunc(inputn(&date.01,yymmdd8)),&months),yymmn6)
%mend;

Но если вам нужен метод, который вы можете использовать со значениями переменных в обычных операторах SAS, тогда не используйте%sysfunc() вообще.Вместо этого просто используйте макрос для генерации кода SAS для непосредственного вызова функций.

%macro add_months_sas(date,months);
input(put(intnx('month',input(cats(&date,'01'),yymmdd8.),&months),yymmn6.),6.)
%mend;

Так что ваше предложение WHERE будет выглядеть так:

WHERE %add_months_sas(T1.old_date, T1.x_months) > 201801 

Но вы должны действительнопросто преобразуйте цифры в фактические даты, а затем используйте функцию INTNX() для добавления месяцев. Тогда макросы вообще не нужны.

WHERE intnx('month',T1.old_date, T1.x_months) > '01JAN2018'd  
1 голос
/ 12 марта 2019

Если вы работаете с относительно новой версией SAS, вы должны поделиться ею как функцией FCMP, а не как с макро-функцией.

proc fcmp позволяет создавать (и сохранять) пользовательские функции, которыевызывается из шагов данных и proc sql (а также с помощью таких вещей, как %sysfunc()).

Вот пример функции fcmp, которая возвращает случайное число между двумя указанными числами:

proc fcmp outlib=work.funcs.funcs;
  function randbetween(min,max);
    return ( min + floor( ( 1 + max - min ) * rand("uniform") ) );
  endsub;
run;        

Пример использования:

data example;
 do cnt=1 to 5;
   x = randbetween(1,100);
   output;
 end;
run;

Результат:

Obs cnt x
1   1   8
2   2   93
3   3   98
4   4   97
5   5   12

Если вы получаете какие-либо жалобы от SAS на то, что вы не признаете вашу функцию, вам может потребоваться обновить ваши параметры, чтобы что-тостроки: options cmplib = (work.funcs);

...