Лекция 5. Программирование на языке SAS. Макропроцессор (1185377), страница 2
Текст из файла (страница 2)
. .MLOGIC(MY_MACRO_FUN1):Ending execution.21Параметры в макроопределениях• В макроопределения можно передавать параметры.%macro my_macro_fun1(dataset, vars);proc print data=&dataset;var &vars;run;1 аргумент2 аргумент%mend;%my_macro_fun1(ecprg1.donate,employee_id qtr amount)LOG:NOTE: The macro MY_MACRO_FUN1 completed compilation without errors.9 instructions 232 bytes.20%my_macro_fun1(ecprg1.donate,employee_id qtr amount)MLOGIC(MY_MACRO_FUN1): Beginning execution.MLOGIC(MY_MACRO_FUN1): Parameter DATASET has value ecprg1.donateMLOGIC(MY_MACRO_FUN1): Parameter VARS has value employee_id qtr amountSYMBOLGEN: Macro variable DATASET resolves to ecprg1.donateMPRINT(MY_MACRO_FUN1):proc print data=ecprg1.donate;SYMBOLGEN: Macro variable VARS resolves to employee_id qtr amountMPRINT(MY_MACRO_FUN1):var employee_id qtr amount;MPRINT(MY_MACRO_FUN1):run;NOTE: ...MLOGIC(MY_MACRO_FUN1):Ending execution.22Параметры в макроопределениях• В макроопределениях можно задать параметры с помощью двух нотаций(позиционная и по ключевому слову).
значение параметра поумолчанию, а также передавать параметры в макроопределение впроизвольном порядке%macro my_macro_fun1(dataset, var1=employee_id,var2=qtr, var3= );proc print data=&dataset;var &var1 &var2 &var3 ;run;%mend;%my_macro_fun1(ecprg1.donate)LOG: .LOG:. .MLOGIC(MY_MACRO_FUN1): Parameter DATASET has value ecprg1.donateMLOGIC(MY_MACRO_FUN1): Parameter VAR1 has value employee_idMLOGIC(MY_MACRO_FUN1): Parameter VAR2 has value qtrMLOGIC(MY_MACRO_FUN1): Parameter VAR3 has value%my_macro_fun1(ecprg1.donate,var2=amount). . .MLOGIC(MY_MACRO_FUN1): Parameter VAR2 has value amountMLOGIC(MY_MACRO_FUN1): Parameter VAR1 has value employee_idMLOGIC(MY_MACRO_FUN1): Parameter VAR3 has value23Условный переход%if &var = CHANGE %then%do;...ПОДСТАНОВКА1%end;%else %if &var = SAME %then%do;...ПОДСТАНОВКА2%end;• В условии, которое проверяет оператор %if, должны находитьсямакропеременные и/или макрофункции, то есть то, с чем может«разобраться» макропроцессор на момент вызова этого выражения.• Оператор %if можно вызвать только внутри макроопределения:15%let var=1;16%if &var =0 %thenERROR: The %IF statement is not valid in open code.17%do;• Проверяемое выражение должно возвращать «число», в противномслучае макропроцессор выдаёт ошибку.24Операции, которые можно использовать для %if•Список (IN) (не работает без options minoperator;)151617181920true•0 = false, <>0 = true1516171819False•%macro test;%let var=A;%if &var IN A B C D %then %put true;%else %put false;%mend;%test%macro test;%if 0 %then %put true;%else %put false;%mend;%testУсловие вычисляется после разрешения макропеременных1617181920212223true%macro test;%let var=1;%let oper= ~;%let var2=0;%if &var &oper &var2 %then %put true;%else %put false;%mend;%test25SAS(R) Macro Language: Reference->Macro Expressions->Defining Arithmetic and Logical ExpressionsМакрофункцииВыполняются на этапе работы макропроцессора, нужны дляобработки значений макропеременных%UPCASEПриведение к верхнему регистру%SUBSTRПоиск подстроки в строке%SCANРазбиение на лексемы по разделителю%INDEXПоиск символа в строке%EVALВычисляет арифметическое выражение%SYSFUNCЗапускает SAS функцию на этапе препроцессора%STRМаскирует спец.
символы%NRSTRМаскирует спец. символы, включая макротриггерыМакрофункции• %SYSEVALF(expression<, conversion-type> )Вычисление арифметических и логических операций (в т.ч. с нецелыми числами)154.9%put %sysevalf(4+0.9);• %SYSFUNC (function(argument-1 <...argument-n>)<, format> )Выполняет функцию SAS и возвращает результат1611719498%put %sysfunc(ceil(0.9));%put %sysfunc(today());• %NRSTR (character-string)Экранировка служебных символов, в том числе «&», «,»15%let xstring1=&VARVAR;16%let xstring2=%nrstr(&VARVAR);17%put &xstring1;WARNING: Apparent symbolic reference VARVAR not resolved.&VARVAR18%put &xstring2;&VARVAR•%SUBSTR (argument, position<, length> )19umen%put %SUBSTR (argument, 4, 4 ) ;27Работа с макропеременными• Если макропеременная содержит цифру, что с ней можно сделать?• Арифметические и логические операции:%let%let%put%let%put%let%let%puta=8;b=&a+8; /* wrong!*/&b;b=%sysevalf(&a+8); /* 16 */&b;c=%sysevalf(&a>&b); /* 0 */d=%sysevalf(&a<&b); /* 1 */&c &d ;• Посчитать какую-нибудь функцию из SAS BASE:%let%let%let%put%let%putpi=3.1415926535;a=%sin(&pi); /* what is "%sin"? */a=%sysfunc(sin(&pi));&a; /* almost 0 */a=%sysfunc(tan(&pi/2));&a; /* something goes wrong */WARNING: An argument to the function TAN referenced by the %SYSFUNC or %QSYSFUNC macrofunction is out of range.NOTE: Mathematical operations could not be performed during %SYSFUNC function execution.The result of the operations have been set to a missing value.28Циклы•••••Можно использовать только внутри макроопределений.Справка: %DO, Iterative Statement ; %DO %UNTIL Statement ; %DO %WHILEStatementПример: создание 10 наборов данных, внутри каждого – по 10 наблюдений%macro test;%do i=1 %to 10;data test&i;do i=1 to 10;output;end;run;%end;%mend;%testВ примере шаг DATA с 10 разными названиями набора данных будетвыполнен 10 раз.В циклах SAS MACRO можно использовать макроопределения имакропеременные.29Генерация и запуск кода с помощью EXECUTECALL EXECUTE (argument);Аргумент:The following occurs:Макро кодМакрокод для генерации SAS кода запускается вовремя текущего шага, приостанавливая его, асгенерированный SAS коду уже на следующем шагеSAS кодДанный код запускается после завершениятекущего шагаГенерация кода с помощью FILE, PUT ипоключение с помощью оператора %INCLUDE• Код пишется как обычный внешний текстовый файл через FILE и PUT• Затем подключается с помощью %INCLUDE и выполняется вследующем шаге• Преимущества использования FILE/PUT для генерации кода:• большая гибкость генерации кода по сравнению с использованиеммакросов;• исходный код можно сохранять для будущего использования;• код можно посмотреть перед его выполнением;• одновременно можно записать несколько файлов; эти файлы представляютсобой полную программу;• код можно использовать для написания макрокода (динамическихмакроимен).Работа с файлами на этапе макроподстановки• Все делается через %SYSFUNC• Работа с файлами (все возвращают 0 если успех):– Открытие набора данных OPEN (data-set name)– Чтение атрибутов набора данных ATTRN(data-set-identifier, attribute)– Создание макропеременных для всех переменных исходного набораCALL SET(data-set-identifier);– Чтение одного наблюдения FETCH(data-set-identifier), возвращает 0 –успех, 1 – конец файла– Закрыть набор CLOSE(data-set-identifier)32Работа с директориями на этапемакроподстановки• Привязать имя файла или директории– FILENAME(fileref, filename < ,device < ,host-options < ,dir-ref > > >)• Аналогично файлам:– Открытие директории DOPEN(fileref)– Получение числа элементов DNUM(directory-ID)– Чтение элемента директории по номеру DREAD(directory-ID, membernumber)– Закрытие директорииDCLOSE(directory-ID)• Пример:найти все наборы sasв директории33Пример программы с макросами для транспонированиятаблицы• Чтобы заменить повторяющиеся части кода на макроопределениенам нужно знать кол-во наблюдений в исходной таблице (или кол-востолбцов в транспонированной)data _null_;set table end=_tab;if _tab then call symputx('tabnobs',_N_);run;%put &tabnobs;••Макропеременная определ.
до шага DATA, где используется!Теперь можно создать макроопределение:%macro readall;%do i=1 %to &tabnobs;_no= &i;set table(keep=c1) point=_no;row&i = c1;%end;%mend;data transposed2;%readalldrop c1;output;stop;run;data transposed1;_no=1;set table(keep=c1)point=_no;row1 = c1;_no=2;set table(keep=c1)point=_no;row2 = c1;drop c1;output;stop;run;34Пример программы с макросами для транспонированиятаблицыКак будет работать программа (шаг DATA) после компиляции макросов?%macro readall(j);%do i=1 %to &tabnobs;_no= &i;set table(keep=c&j) point=_no;row&i = c&j;%end;drop c&j;%mend;%macro doallcols;%do j=1 %to 4;%readall(&j)output;%end;%mend;data transposed2;%doallcolsstop;run;Мы 4 раза вызываем макрос readallj, читающий данные из однойзаданной колонки исходной таблицы в новое наблюдение длятранспонированной таблицы.В какую программу «развернутся» эти два макроопределения? Этоможно реконструировать из log:1 data transposed2;2_no= 1;3set table(keep=c1)4row1 = c1;5_no= 2;6set table(keep=c1)7row2 = c1;8drop c1;9output;10_no= 1;11set table(keep=c2)12row1 = c2;13_no= 2;14set table(keep=c2)15row2 = c2;16drop c2;17output;18_no= 1;19set table(keep=c3)20row1 = c3;21_no= 2;22set table(keep=c3)23row2 = c3;24drop c3;25output;26_no= 1;27set table(keep=c4)28row1 = c4;29_no= 2;30set table(keep=c4)31row2 = c4;32drop c4;33output;34 stop;35 run;point=_no;point=_no;point=_no;point=_no;point=_no;point=_no;point=_no;point=_no;35.