Как я могу выполнить часть макроса для каждого наблюдения в шаге данных SAS? - PullRequest
5 голосов
/ 09 июня 2011

Предположим, я разрешаю пользователю написать свой собственный макрос вычисления переменных с использованием общего пользовательского интерфейса:

%macro calculate(var_name, var_value);
%* Some user-defined calculation;
%mend calculate;

Затем на шаге данных я могу вычислить новую переменную, используя определяемый пользователем макрос:

data dataset;
    set dataset;
    new_var = %calculate('variable1', variable1); * This doesn't work. It just shows my indication.
run;

Где variable1 - переменная в наборе данных.Здесь я хочу передать имя переменной и фактическое значение переменной.После расчета поместите значение в new_var.

Как этого добиться?

Ответы [ 4 ]

6 голосов
/ 09 июня 2011

Требуется ли это для достижения макросов? Это похоже на ситуацию, в которой PROC FCMP будет наиболее полезным, поскольку она позволяет вам определять свои собственные функции или подпрограммы (fcmp = "компилятор функций"), которые могут использоваться на шаге данных, как встроенные в функции.

Вот простой пример:

proc fcmp outlib=sasuser.funcs.math;
  function calc(var);
     newvar=log(var); /*user defined stuff here - can be simple or complex*/
     return(newvar);
  endsub;
run;

option cmplib=sasuser.funcs; /*tell SAS where to look for functions*/
data _null_;
  set sashelp.class;
  newvar=calc(height); /*call your new function */
  put newvar=;
run;
3 голосов
/ 09 июня 2011

Вы можете сделать это, но вы, вероятно, пишете макрос неправильно. Вы должны помнить, что макросы SAS по сути являются текстовыми препроцессорами: они вводят написанный вами код и выводят код для подачи в SAS [1].

Итак, вот простой макрос «сложения»:

%macro calculate (var_name, var_value);
  &var_name + &var_value;
%mend;

data one;
  input a@@;
  b = %calculate(a, 3);
  c = %calculate(a, a);
cards;
1 3 -2 4
;
run;

proc print data=one;
run;

Средство макроса заменит биты %calculate кодом, сгенерированным макросом, и SAS фактически увидит следующее:

%macro calculate (var_name, var_value);
  &var_name + &var_value;
%mend;

data one;
  input a@@;
  b = a + 3;
  c = a + a;
cards;
1 3 -2 4
;
run;

proc print data=one;
run;

Вы можете увидеть это в файле журнала с помощью оператора options mprint

К сожалению, это не охватит все потенциальные расчеты. Возможно, вы захотите найти в PROC FCMP способ генерации пользовательских функций / подпрограмм, используемых на шаге DATA.

[1] Я знаю, что это сложнее, чем это, но вы можете далеко подумать, как это.

2 голосов
/ 26 февраля 2016

Я знаю, что это более старый пост, но я думаю, что стоит упомянуть об этом.

Вот решение, которое позволяет использовать макропрограмму как функцию.Это достигается с помощью функции SAS resolve().То, что следует за «% тогда» (в данном случае это текст, но это может быть число), соответствует тому, что мы поместили бы в return () части «реальной функции».

%macro compare(v1, v2);
  %if &v1 > &v2 %then v1 is greater than v2;
  %else v2 is greater than v1;
%mend;

data check (drop = macroCall);
  input v1 v2;
  macroCall = cats('%compare(', v1, ',', v2, ')');
  result = resolve(macrocall);
  datalines;
1 2
2 1
;

Результаты:

v1  v2  result
1   2   v2 is greater than v1
2   1   v1 is greater than v2
0 голосов
/ 11 июня 2011

Это общая точка путаницы.Проблема в том, что SAS обрабатывает весь код макроса в вашей программе ДО любого обычного кода.Поэтому, когда он вызывает %calculate('variable1', variable1);, у него еще нет доступа к данным в наборе данных.

Тем не менее, было бы легче помочь вам найти решение, если бы у меня был примерчто вы можете иметь в виду под %*Some user-defined calculation;.

...