无法将 SAS 宏应用于列

Unable to apply a SAS macro to a column

我想将我编写的宏应用到 SAS 中的每一行

DATA cars1;
INPUT make $ model $ mpg weight price;
CARDS;
AMC Concord 22 2930 4099
AMC Pacer   17 3350 4749
AMC Spirit  22 2640 3799
Buick Century 20 3250 4816
Buick Electra 15 4080 7827
;
RUN; 

%macro calculate1 (var_name, var_value);
%If &var_name < 20 %then
%do;
&var_value + &var_name;
%end;
%else %if &var_name >= 20 %then
%do;
&var_value - &var_name;
%end;
%mend ;

Data cars2; Set cars1;
varnew = %calculate1(mpg, weight);
Run;

当我 运行 这段代码时,即使 MPG 值小于 20,我也会得到两列之间的差异,根据代码,如果 MPG 列中的值为,我想要列的总和< 20.

我知道我可以使用列的 If 条件,但我想尝试使用宏来执行此操作。

请帮我在列上应用我的宏。

提前致谢。

您很可能还不需要宏代码。

宏在 运行 时间之前编写 SAS 源代码,它不会在 运行 时间评估数据步骤表达式。

在尝试将其抽象为宏之前先学习编写数据步骤代码。

数据步骤

可能包含您希望宏生成

的源代码语句(if/then/else)
data cars2;
  * calculate;
  if mpg < 20 then varnew = weight + mpg;
  else
  if mpg >= 20 then varnew = weight - mpg;
run;

这将如何抽象?确定 if/then/else 的哪些组件将在不同的上下文或不同的变量中重用。如果您不能确定重复使用,请不要编写宏。

考虑生成完整语句的抽象 #1(作为伪代码)

  if PARAMETER_2 < 20 then RESULT_VAR = PARAMETER_1 + PARAMETER_2;
  else
  if PARAMETER_2 >= 20 then RESULT_VAR = PARAMETER_1 - PARAMETER_2;

或为表达式生成源代码的抽象#2

  ifn (PARAMETER_2 < 20, PARAMETER_1 + PARAMETER_2, PARAMETER_1 - PARAMETER_2)

但为什么要将 20 硬编码到宏中?为什么不把它也作为一个参数呢?如果你走那条路,抽象太多了,并且正在模板化应该以非宏方式使用的实际语言元素。 (人们可能会认为在像 LISP 这样的纯函数式语言中没有太多的抽象)

作为宏的抽象 #1

%macro calculate(result_var, parameter_1, parameter_2);
  /* generate DATA Step source code, using the passed parameters */

  if &PARAMETER_2 < 20 then &RESULT_VAR = &PARAMETER_1 + &PARAMETER_2;
  else
  if &PARAMETER_2 >= 20 then &RESULT_VAR = &PARAMETER_1 - &PARAMETER_2;
%mend;

data cars2;
  %calculate(varnew,weight,mpg);
run;

作为宏的抽象 #2

%macro calculate(parameter_1, parameter_2);
  /* generate source code that is valid as right hand side of assignment */

  ifn (&PARAMETER_2 < 20, &PARAMETER_1 + &PARAMETER_2, &PARAMETER_1 - &PARAMETER_2)
%mend;

data cars2;
  varnew = %calculate(weight,mpg);
run;