SAS宏流解释

SAS宏流解释,sas,sas-macro,Sas,Sas Macro,遵循此模式 我可以理解,宏在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 = "p

遵循此模式

我可以理解,宏在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和一个OUT变量 为了避免这种情况,您可以使用宏if-else,因为只有true子句对数据步骤可见。例如:

%if "&var" = "pippo"n %then in0_&var = name;
%else out0_&var = name; 
但是,如果将var用作变量,这将不起作用,因为这样会得到in0_name而不是name的变量值,因为宏编译器不知道变量“name”的值

此外,您还必须小心如何使用宏变量,如果它应该在数据步骤中用作字符串,则必须使用“&var”,否则它将被解释为变量

宏解析所有带有该宏值的&-值,然后数据步骤解释该步骤。 因此,在这种情况下,您不需要宏,只需在datastep中使用if-else而不是宏调用,例如:

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\u pippo
的值设置为
name
的值,并且不会将任何值分配给
OUT0\u pippo

如果将其称为
var
的某个其他值,例如
FRANK
,则它会将该变量的值与
PIPPO
进行比较

在您调用此宏的示例数据步骤中,没有名为
pippo
frank
的变量,因此当您引用它们时,SAS将创建具有缺失值的新变量。因此,它们将始终相等。因此,所有INO…变量都将设置为
NAME
的值,而所有OUT0…变量都将设置为bles将被取消分配


您发布的图片显示SAS已经完成了您要求它做的事情。

应该是:如果“&var”=“pippo”n那么…因为您想在这里比较字符串?这至少会删除空名称列…就像您现在查找名为pippo、arj……的变量的方式一样,并将它们与字符串“pippo”进行比较“诺克,我已经改正了,但我还是不明白答案。输出与输入完全相等。在任何情况下,就像python程序调用一个方法或函数一样,我只希望得到“out\var.”列的名称,但是还有很多列,我真的不知道它们来自哪里。我不确定你打算做什么。此时,对于数据集中的每一行,使用不同的名称调用宏5次。因此,输出正如我所期望的。你期望结果是什么?是的,我删除了我的答案,因为我仍然不确定你期望的输出应该是什么样子。也许你可以把你的预期结果加到这个问题上?对不起,我认为你是对的。如果“&var”n=。。。只调用一次名称为值的宏。%测试(名称)。这就是我想要的输出。但我的问题仍然悬而未决。SAS是如何工作的?谢谢。事情变得越来越清楚了。还有一件事。我希望每个名字都有一列。类似于“in_name”,其中name是我的数据集的单元格值。无论如何,答案很好,我需要更深入地研究它,以充分了解宏和变量的用法。@arj:Hm,问题是宏编译器不知道变量名的值,因此必须使用字符串调用宏。如果您知道应该为哪一行使用哪一个字符串,您可以使用类似If n_u=1然后%test(pippo);如果_n=2,则为%test(arj)。。。在宏中使用宏if-else,这是我在回答中描述的很棒!我以后会多次查看这篇文章。非常感谢。也会有一些解决方案为每个名称创建一个变量,但我认为所有这些都有点复杂,也许我会在以后添加一个。我想说,如果你想知道如何精确地做到这一点,这应该是它自己的问题-这个问题有它的答案。有很多很好的方法可以准确地做你想做的事情,但是你应该问这个问题,并提供准确的预期结果。