如何在sas数据步骤中为每个观察执行一段宏?

时间:2011-06-09 06:38:18

标签: sas

假设我允许用户使用通用用户界面编写自己的变量计算宏:

%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 个答案:

答案 0 :(得分:6)

是否需要使用宏实现此目的?这听起来像PROC FCMP最有用的情况,因为它允许您定义自己的函数或子例程(fcmp =“函数编译器”),它们可以像数据内置函数一样在数据步骤中使用。 / p>

这是一个简单的例子:

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;

答案 1 :(得分:3)

你可以使这个工作,但你可能错误地编写宏。您必须记住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 :(得分:2)

我知道这是一篇较老的帖子,但我认为值得一提。

这是一个允许像使用函数一样使用宏例程的解决方案。这是在SAS resolve()功能的帮助下完成的。随后的“%then”(在这种情况下它是文本,但它可能是一个数字)对应于我们将放在“真实函数”的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

答案 3 :(得分:0)

这是一个常见的混淆点。问题是SAS在任何常规代码之前处理程序中的所有宏代码。因此,当它调用%calculate('variable1', variable1);时,它还无法访问数据集中的数据。

也就是说,如果我有一个%*Some user-defined calculation;可能含义的例子,那么帮助你提出解决方案会更容易。