SAS - создание макросов динамически - PullRequest
0 голосов
/ 08 октября 2018

Я хотел бы динамически создавать макросы для запроса набора транзакционных данных.У меня есть таблица, которая имеет набор параметров ( parameter_data ) и данные транзакции ( txs ).Для каждой строки в моих параметрах я хочу создать макрос, который можно вызывать для запроса данных.

Данные параметров:

data parameter_data;
input macro_name $ parameter_name $ parameter_value $;
datalines;
A Person_ID 1
B TX_ID 2
;

Транзакционные данные:

data txns;
input Person_ID $ TX_ID $ TX_Amount $;
datalines;
John Sales 1123
Mary Acctng 34
John Sales 23
Mary Sales 2134
;

Здесь я пытаюсь создать макрос, который должен динамически создавать макросы в соответствии с данными параметров.«Внутренние макросы» - это макросы, которые создаются из данных параметров.

%macro outerMacro;

/*loop through each row in the parameter table to get the detail of the macro we want to create*/
%DO ROW = 1 %To 2;
data _NULL_;
set parameter_data;
if _N_ = ROW then do;
    call symputx('parameter_name',parameter_name);
    call symputx('parameter_value',parameter_value);
    end;
run;

/*define inner macro parameters*/
%let macroName = myMacro; /*set the name of the macro we want to create*/
%let innerMacroStart = macro &macroName.; /*set the macro name to start the macro definition*/
%let innerMacroEnd = mend &macroName;

%&&innerMacroStart.; /*start the inner macro*/

    /*body of the macro*/
    data output;
    set txns;
    &&parameter_name = &&parameter_value; 
    /*so here effectively for the first row in the parameter table we are filtering where person_id = John*/
    run;

%&&innerMacroEnd.; /*end the inner macro*/

%mend outerMacro;

%&&outerMacroName.;

Кажется, что SAS не может проанализировать строки% innerMacroStart.Любая помощь очень ценится.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Я разместил комментарий перед каждым блоком кода, но по сути это:

  1. Настройка параметров.
  2. Создание макросов.
  3. % include.
  4. Вызов любого нужного макроса.

Я предположил не более 999 наблюдений параметров - это контролируется seq.

Вы можете проверить файл "inner_macro.sas ", чтобы увидеть определения макросов.

NB. При попытке использовать собственный путь вместо <your-path> (встречается дважды):

/* set up parameters */
data parameters;
   infile datalines dlm=',';

   input var      : $8.
         operator : $8.
         value    : $8.
   ;

   datalines;
name,eq,"John"
age,gt,12
weight,eq,0
;

/* read parameters and generate a macro definition for each obs, written to a file */
data _null_;
   file '<your-path>/inner_macro.sas';

   set parameters;

   seq = put(_n_,z3.);

   put '%macro inner_' seq ';';
   put '    where ' var operator value ';';
   put '%mend inner_' seq ';';
   put;
run;

/* %include (submits code in file) all of the macro definitions */
%include '<your-path>/inner_macro.sas';

options mprint;

/* invoke the macro with the required data sets */
data class1;
   set sashelp.class;
   %inner_001;
run;

data class2;
   set sashelp.class;
   %inner_002;
run;

data class3;
   set sashelp.class;
   %inner_003;
run;
0 голосов
/ 08 октября 2018

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

data _null_;
  set parameter_data ;
  call symputx(macro_name,catx(' ','where also'
              ,parameter_name,'=',quote(trim(parameter_value)),';'));
run;

Затем просто используйте сгенерированные операторы where, когда они вам нужны, путем расширения макропеременной.Например:

data output ;
  set txns;
  &a 
run;

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

Давайте исправим ваш файл параметров, чтобы он лучше соответствовал вашим тестовым данным.Person_ID и TX_ID являются символьными переменными в вашем наборе данных транзакций.Возможно, вам потребуется добавить логику или изменить файл параметров, чтобы он мог обрабатывать как числовые, так и символьные переменные.На данный момент я только что сгенерировал код, который предполагает, что PARAMETER_NAME ссылается на символьную переменную, так что PARAMETER_VALUE нужно будет добавить кавычки, чтобы сделать его строковым литералом.

data parameter_data;
input macro_name :$32. parameter_name :$32. parameter_value $:200.;
datalines;
A Person_ID John 
B TX_ID Acctng 
;

data txns;
input Person_ID $ TX_ID $ TX_Amount $;
datalines;
John Sales 1123
Mary Acctng 34
John Sales 23
Mary Sales 2134
;

Теперь давайте запустим шаг данных, чтобы сгенерироватькод для всех ваших макросов.Я добавил логику, чтобы использовать AND, если для каждого макроса определено несколько «параметров».

filename code temp;
data _null_;
  set parameter_data ;
  by macro_name ;
  file code ;
  if first.macro_name then put
  '%macro ' macro_name ';' 
/ 'data output;'
/ '  set txns;'
/ '  where ' @ 
  ;
  else put ' and ' @ ;
  put parameter_name '=' parameter_value :$quote. @ ;
  if last.macro_name then put
  ';'
/ 'run;'
/ '%mend ' macro_name ';'
  ;
run;

Теперь просто используйте% include для компиляции макросов.

%include code / source2 ;

NOTE: %INCLUDE (level 1) file CODE is file C:\...\#LN00048.
432  +%macro A ;
433  +data output;
434  +  set txns;
435  +  where Person_ID ="John" ;
436  +run;
437  +%mend A ;
438  +%macro B ;
439  +data output;
440  +  set txns;
441  +  where TX_ID ="Acctng" ;
442  +run;
443  +%mend B ;
NOTE: %INCLUDE (level 1) ending.

Теперь выможете использовать ваши макросы.

445   options mprint;
446   %a ;
MPRINT(A):   data output;
MPRINT(A):   set txns;
MPRINT(A):   where Person_ID ="John" ;
MPRINT(A):   run;

NOTE: There were 2 observations read from the data set WORK.TXNS.
      WHERE Person_ID='John';
NOTE: The data set WORK.OUTPUT has 2 observations and 3 variables.

447   %b ;
MPRINT(B):   data output;
MPRINT(B):   set txns;
MPRINT(B):   where TX_ID ="Acctng" ;
MPRINT(B):   run;

NOTE: There were 1 observations read from the data set WORK.TXNS.
      WHERE TX_ID='Acctng';
NOTE: The data set WORK.OUTPUT has 1 observations and 3 variables.
...