无法将 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;
我想将我编写的宏应用到 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;