SAS BASE. Программирование на языке SAS BASE. Основы (1185351), страница 4
Текст из файла (страница 4)
Разделения на символьный и числовой тип – нет.• Математические выражения не выполняются• Регистр хранимого текста сохраняется• Минимальная длина 0 символов, максимальная – 65534 симв.• Пробелы с начала и с конца значения удаляются.• Значение макропеременной «живёт» до конца сеанса (или завершенияпроцесса SAS)• …или до применения макрофункции %symdel ;52Пользовательские макропеременные• Вывод в log значения макропеременной:%put &numb_of_obs ;• Подстановка макропеременной в программу:proc print data=ecprg1.donate(obs=&numb_of_obs);run;• Log:1516101718%let numb_of_obs = 10 ;%put &numb_of_obs ;proc print data=ecprg1.donate(obs=&numb_of_obs);run;• По умолчанию все средства для отладки выключены, и мы не видимсообщений от макропроцессора.• Макропеременные можно подставлять одну в другую:151617aaa bbb%let x=aaa;%let x=&x bbb;%put &x;• Задание явной границы (.) в коде для названия макропеременной:151617aaabbb%let x=aaa;%let x=&x.bbb;%put &x;53Отладка макропеременных• Вывод в log только пользовательских переменных:%PUT _USER_ ;• Вывод в log всех макропеременных:%PUT _ALL_ ;• Включить глобальную опцию symbolgen:151617SYMBOLGEN:18SYMBOLGEN:aaabbboptions symbolgen;%let x=aaa;%let x=&x.bbb;Macro variable X resolves to aaa%put &x;Macro variable X resolves to aaabbb• Выключить её, если макрос отлажен: options nosymbolgen;• Log всегда содержит информацию об ошибках разрешениямакроподстановок:17%let x=&x11.bbb;WARNING: Apparent symbolic reference X11 not resolved.18%put &x11;WARNING: Apparent symbolic reference X11 not resolved.&x1154Работа с макропеременными•Подстановка переменных в программу:1516171819%let library= ecprg1 ;%let dataset= donate ;data temp1;set &library..&datasetrun;;NOTE: There were 16 observations read from the data set ECPRG1.DONATE.NOTE: The data set WORK.TEMP1 has 16 observations and 3 variables.• Подстановка переменной в символьные константы:Одинарные кавычки – макропроцессор не подставляет значениемакропеременной, двойные кавычки – подставляет:1516171819Privet!&text1•%let text1= Privet! ;data _null_;put "&text1";put '&text1';run;Автоматические макропеременные:SYSDATE, SYSDATE9, SYSDAY, SYSTIME – дата, день недели и время, когда был запущенпроцесс SAS (могут отличаться от текущих!)SYSLAST – название самого последнего набора данных, который был созданSYSERR – код возврата шага DATA или PROC (0=ошибок нет)SYSLIBRC – код возврата оператора LIBNAME (создание ссылки на библиотеку,0=ошибок нет)55Программирование на языкеSAS BASEЛекция 3:Макросы и SQLЗвежинский Дмитрий,SAS Russia/CISdmitry.zvezhinsky@sas.comЗамечания об ошибках и опечатках просьба направлять лектору.56Решение домашних заданийНам нужны рабочие программы (не проекты)с вашим sas code на адресacademy@rus.sas.comс пометкой в subject “VMK Course Task #” сномером задания.57Макроопределения••Макропроцессор может динамически создавать код, используя заданныешаблоны для макроподстановки.Шаг 1.
Определение макрофункции.%macro my_macro_fun;proc print data=ecprg1.donate;var employee_id qtr amount;run;%mend;•Макропроцессор запомнит этот кусок кодаШаг 2. Вызов макрофункции: если макроопределение было занесено вмакропроцессор, оно подставляется в сеанс и выполняется.%my_macro_funКомпиляция и выполнение шага происходит, когда будут разрешены (=подставлены)все макропеременные, то есть можно писать что-то типа:%macro my_macro_fun1;proc print data=ecprg1.donate;%mend;%macro my_macro_fun2;var employee_id qtr amount;%mend;%my_macro_fun1%my_macro_fun2run;Вопрос: чем отличаются макроопределенияот макропеременных?(ответа пока не было)58Порядок выполнения макроопределенияЭтот код компилируется (запоминается)15options mcompilenote=all;макропроцессором, т.к.
он не содержит16%macro test1;ошибки макро-синтаксиса, но в нем могут17data _null_;присутствовать другие виды ошибок18a=&ttt;(разрешение макро переменных, или19run;ошибки SAS BASE)20%mend;NOTE: The macro TEST1 completed compilation without errors.5 instructions 88 bytes.21%test1MLOGIC(TEST1): Beginning execution.NOTE: Line generated by the invoked macro "TEST1".21data _null_;a=&ttt;run;Обратите внимание, что макро_переменные разрешаются после22выполнения макроопределенияMPRINT(TEST1):data _null_;WARNING: Apparent symbolic reference TTT not resolved.MPRINT(TEST1):a=&ttt;MPRINT(TEST1):run;Макропеременной «ttt» не существует, ошибка вразрешении этой переменной привела к появлениюв программе SAS непонятной конструкции59Отладка макроопределений•Options mcompilenote=ALL;NOTE: The macro MYMACRO completed compilation without errors.•••Options mlogic;Помогает отлаживать условные переходы в макропрограммахOptions mprint;Печатает код, который генерируется макросомСписок макроопределений (не работает в on-demand)proc catalog cat=work.sasmacr;contents;run;quit;•Список макропеременных: служебное представление sashelp.vmacro•Отключите все отладочные опции (Options mcompilenote=NONEnomlogic nomprint; ) после отладки.60Вызов макроопределений• Макропеременные можно подставлять в макроопределения.Options mcompilenote=ALL mlogic mprint symbolgen;%let dataset=ecprg1.donate ;Определяем макропеременные%let vars=employee_id qtr amount;%macro my_macro_fun1;proc print data=&dataset;Определяем макроопределениеvar &vars;run;%mend;Вызов макроопределения%my_macro_fun1LOG:16%let dataset=ecprg1.donate ;17%let vars=employee_id qtr amount;18%macro my_macro_fun1;19proc print data=&dataset;20var &vars;21run;22%mend;NOTE: The macro MY_MACRO_FUN1 completed compilation without errors.5 instructions 104 bytes.23%my_macro_fun1MLOGIC(MY_MACRO_FUN1): Beginning execution.SYMBOLGEN: 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.61Параметры в макроопределениях• В макроопределения можно передавать параметры.%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.У макропеременных есть области видимости, см help -> Examples of Macro VariableScopes.
Областью видимости переменной можно принудительно управлять спомощью %global (перем. видна во всем макрокоде) и %local (только в данном62макросе)Параметры в макроопределениях• В макроопределениях можно задать параметры с помощью двух нотаций(позиционная и по ключевому слову). значение параметра поумолчанию, а также передавать параметры в макроопределение впроизвольном порядке%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 value63Условный переход%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;••Проверяемое выражение должно возвращать «число», в противном случаемакропроцессор выдаёт ошибку.Чтобы вычислить арифметическое выражение в макропроцессоре, нужноиспользовать функцию %eval(…).
Её особенность – принимает только целыеаргументы и округляет результат до целого.ERROR: A character operand was found in the %EVAL function or %IF condition where anumeric operand is required. The condition was:4+0.915%put %eval(4+0.9);160%put %eval(1/3);64Операции, которые можно использовать для %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;%test65SAS(R) Macro Language: Reference->Macro Expressions->Defining Arithmetic and Logical ExpressionsМакрофункции• %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•19umen%SUBSTR (argument, position<, length> )%put %SUBSTR (argument, 4, 4 ) ;* см.
SAS® 9.3 Macro Language Reference66Циклы•••Можно использовать только внутри макроопределений.Справка: %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 можно использовать макроопределения имакропеременные.67Symputx• Вы можете создать макропеременную на шаге DATA15161718data _null_;set ecprg1.donate end=_tab;if _tab then call symputx('tabnobs',_N_);run;NOTE: There were 16 observations read from the data set ECPRG1.DONATE....19%put &tabnobs;16• Вы можете прочитать макропеременную на шаге DATAdata donatelast;lastobs=input(symget('tabnobs'),5.);put lastobs;set ecprg1.donate point=lastobs;output;stop;В чем отличия от этой программы:data donatelast;set ecprg1.donate point=&tabnobs;output;stop;run;run;• Symget возвращает значение символьного типа, даже если вмакропеременной хранилось число (в этом случае нужно выполнитьпреобразование типов).• Ключ “point=“ оператора “set” позволяет прочесть наблюдение суказанным номером во входящем наборе данных, при этом указывается68название переменной числового типа (где хранится номер наблюдения)Программа с макросами для транспонирования таблицы*Будем последовательно решать эту задачу, заодно вспомним некоторыеособенности шага DATA.Первый шаг – написать программу (или её часть) без макросов и подумать,где нам понадобятся макросы (м.б.
для каких-то общих случаев?).data table;input c1 c2 c3 c4;datalines;1 2 3 45 6 7 8;run;data transposed1;_no=1;set table(keep=c1)row1 = c1;_no=2;set table(keep=c1)row2 = c1;drop c1;output;stop;run;Операторы input и datalines позволяет задать данныепрямо внутри шага DATA. У нас будет 4 столбца и 2наблюдения.point=_no;point=_no;Транспонируем первый столбец.Прочитаем первое наблюдение,занесём его в столбец row1 нового набора данныхПотом второеИ занесем его в столбец row2 нового набора данных.Выбросим переменную c1Выведем одно (единственное) наблюдениеЯвно остановим шаг DATA (не обязательно).Здесь макросов нет, но есть повторяющийся кусок кода.69* Это - пример для изучения языка программирования, в реальных задачах так лучше не делатьПрограмма с макросами для транспонирования таблицы• Чтобы заменить повторяющиеся части кода на макроопределениенам нужно знать кол-во наблюдений в исходной таблице (или кол-востолбцов в транспонированной)data _null_;set table end=_tab;if _tab then call symputx('tabnobs',_N_);run;%put &tabnobs;••Макропеременная определ.