SAS 宏流程说明
SAS MAcro flow explanation
遵循此架构
我可以理解宏在创建 PDV 之前就已解析。但我真的无法从这段代码中弄清楚如何。
data ds;
input id name $ value ;
datalines;
1 pluto 111
2 paperino 222
3 trump 333
4 topo 444
5 pippo 555
;
run;
%macro test(var) / mindelimiter=',';
if &var = "pippo"n then in0_&var. = name;
else out0_&var. = name;
%mend test;
data want;
set ds;
%test(pippo);
%test(arj);
%test(frank);
%test(pluto);
%test(george);
run;
我得到这个输出
谁能解释一下这个过程的内在逻辑?
据我了解您的评论,您希望得到一个包含 4 列、id、name in 和 out 的结果,并且始终只有 in 或 out 有值。
但是你为每一行调用了 5 次宏。你应该只为每一行调用一次,然后你会得到预期的结果。
在那种情况下,你必须删除我在评论中提到的“at”&var“,因为你在这里使用的是变量,而不是评论(更正了我的代码)
数据步内的变量将被创建,即使它们位于永远不会被使用的 if 或 else 子句中。
因此,您按照以前的方式为调用宏的每个名称创建了一个 in 和一个 outvariable
为避免这种情况,您可以使用宏 if-else,因为只有为真的子句才会对数据步可见。例如:
%if "&var" = "pippo"n %then in0_&var = name;
%else out0_&var = name;
但是如果 var 应该用作变量,这将不起作用,因为那样你会得到 in0_name 而不是 name 的变量值,因为变量 "name" 的值不是为宏编译器所知。
另外你必须小心如何使用宏变量,如果它应该在你的数据步骤中用作字符串,你必须使用“&var”,否则它会被解释为一个变量。
宏用宏值解析所有 &-值,之后数据步骤解释该步骤。
所以在这种情况下你不需要宏,你可以在数据步骤中使用 if-else 而不是你的 macrocall ,例如:
data want;
set ds;
if name = "pippo"n then in0 = name;
else out0 = name;
run;
他们以你想要的方式,你应该使用这个:
%macro test(var) / mindelimiter=',';
if &var = "pippo"n then in0 = name;
else out0 = name;
%mend test;
data want;
set ds;
%test(name); /*This is called for every row in your dataset, so if you have 5 macrocalls,
they will be called 5 times for every row in your dataset*/
run;
如果您有定义的宏。
%macro test(var);
if &var = "pippo"n then in0_&var. = name;
else out0_&var. = name;
%mend test;
并且您调用它时将参数 var
设置为值 pippo
,它将生成代码:
if pippo = "pippo"n then in0_pippo = name;
else out0_pippo = name;
请注意,此代码将 pippo
的值与 pippo
的值进行比较(因为您使用的是名称文字)。这将永远是真的。因此它将始终将 IN0_PIPPO
设置为 NAME
的值,并且永远不会将任何值分配给 OUT0_PIPPO
.
如果您将其称为 var
的其他值,例如 FRANK
,那么它将将该变量的值与 PIPPO
进行比较。
在您调用此宏的示例数据步骤中,没有名为 pippo
或 frank
的变量,因此当您引用它们时,SAS 将创建具有缺失值的新变量。所以他们永远是平等的。因此,所有 INO... 变量都将设置为 NAME
的值,并且所有 OUT0... 变量都将被取消分配。
您发布的图片表明 SAS 完全按照您的要求完成了工作。
遵循此架构
我可以理解宏在创建 PDV 之前就已解析。但我真的无法从这段代码中弄清楚如何。
data ds;
input id name $ value ;
datalines;
1 pluto 111
2 paperino 222
3 trump 333
4 topo 444
5 pippo 555
;
run;
%macro test(var) / mindelimiter=',';
if &var = "pippo"n then in0_&var. = name;
else out0_&var. = name;
%mend test;
data want;
set ds;
%test(pippo);
%test(arj);
%test(frank);
%test(pluto);
%test(george);
run;
我得到这个输出
谁能解释一下这个过程的内在逻辑?
据我了解您的评论,您希望得到一个包含 4 列、id、name in 和 out 的结果,并且始终只有 in 或 out 有值。
但是你为每一行调用了 5 次宏。你应该只为每一行调用一次,然后你会得到预期的结果。
在那种情况下,你必须删除我在评论中提到的“at”&var“,因为你在这里使用的是变量,而不是评论(更正了我的代码)
数据步内的变量将被创建,即使它们位于永远不会被使用的 if 或 else 子句中。 因此,您按照以前的方式为调用宏的每个名称创建了一个 in 和一个 outvariable 为避免这种情况,您可以使用宏 if-else,因为只有为真的子句才会对数据步可见。例如:
%if "&var" = "pippo"n %then in0_&var = name;
%else out0_&var = name;
但是如果 var 应该用作变量,这将不起作用,因为那样你会得到 in0_name 而不是 name 的变量值,因为变量 "name" 的值不是为宏编译器所知。
另外你必须小心如何使用宏变量,如果它应该在你的数据步骤中用作字符串,你必须使用“&var”,否则它会被解释为一个变量。
宏用宏值解析所有 &-值,之后数据步骤解释该步骤。 所以在这种情况下你不需要宏,你可以在数据步骤中使用 if-else 而不是你的 macrocall ,例如:
data want;
set ds;
if name = "pippo"n then in0 = name;
else out0 = name;
run;
他们以你想要的方式,你应该使用这个:
%macro test(var) / mindelimiter=',';
if &var = "pippo"n then in0 = name;
else out0 = name;
%mend test;
data want;
set ds;
%test(name); /*This is called for every row in your dataset, so if you have 5 macrocalls,
they will be called 5 times for every row in your dataset*/
run;
如果您有定义的宏。
%macro test(var);
if &var = "pippo"n then in0_&var. = name;
else out0_&var. = name;
%mend test;
并且您调用它时将参数 var
设置为值 pippo
,它将生成代码:
if pippo = "pippo"n then in0_pippo = name;
else out0_pippo = name;
请注意,此代码将 pippo
的值与 pippo
的值进行比较(因为您使用的是名称文字)。这将永远是真的。因此它将始终将 IN0_PIPPO
设置为 NAME
的值,并且永远不会将任何值分配给 OUT0_PIPPO
.
如果您将其称为 var
的其他值,例如 FRANK
,那么它将将该变量的值与 PIPPO
进行比较。
在您调用此宏的示例数据步骤中,没有名为 pippo
或 frank
的变量,因此当您引用它们时,SAS 将创建具有缺失值的新变量。所以他们永远是平等的。因此,所有 INO... 变量都将设置为 NAME
的值,并且所有 OUT0... 变量都将被取消分配。
您发布的图片表明 SAS 完全按照您的要求完成了工作。