如何在SAS Macro中使用“AND”运算符?

How to use "AND" operators in SAS Macro?

提问人:Lma 提问时间:11/2/2023 更新时间:11/3/2023 访问量:61

问:

我最近编写了一个宏来轻松创建多个“Proc freqs”,只需输入变量和条件“where”(如果有的话)。 它通常有效,但当我的条件“where”包含“AND”时,我一直在努力让它工作。

宏如下:

options mprint minoperator;

%macro check(var1=,var2=,var3=, cond=);

Proc freq data= &dataset_full.; 
Table &var1.
    %if &var2. NE %str() %then 
     * &var2. ;
    %if &var3. NE %str()  %then 
    * &var3. ;
    / out="&var1. &var2. &var3." norow nocol nopercent;
    %if &cond. NE %str() %then
    &cond.;
    ;
Run;

%mend;

例如,我可以写. 不会有错误,它只是不会将我的条件应用于输出。根据 MPRINT 输出,就像“cond”是空的。 相反,如果我的条件包含“OR”,则工作正常。%check(var1=age,var2=weight, cond=where age=1 and weight=10)

我尝试使用 str()、%eval 但它不起作用。

SAS 运算符 过程 逻辑和

评论

0赞 PBulls 11/2/2023
下面的答案有效;问题在于,你将一个逻辑条件抛入一个语句中,然后被解释为该语句的一部分。您的示例变成了 - 我添加了引号来显示字符串比较是如何进行的。第一部分永远不会是真的,并且 where 子句不会被传递。如果在输入中引用逻辑运算符,它们不会影响语句的逻辑。%if%if 'where age'='10' and ...%if
0赞 Quentin 11/2/2023
有一篇关于检查空白宏变量的经典论文,这是一个非常复杂的问题。support.sas.com/resources/papers/proceedings09/022-2009.pdf .
0赞 Tom 11/2/2023
但在这种情况下,您不需要测试“空白”。你可以只测试空,%LENGTH() 就会这样做。

答:

2赞 PeterClemmensen 11/2/2023 #1

2 积分

  1. 您可能应该对 Tables 语句上的 out= 选项执行一些操作。您必须指定 SAS 数据集名称(不在 “” 中)。我猜你想在名称中指定你的输入变量。请参阅下面的代码。
  2. 当使用 %Str 宏函数屏蔽 cond= 值时,下面的代码有效

试试这个

options mprint minoperator;

%macro check(var1=,var2=,var3=, cond=);

Proc freq data= &dataset_full.; 
Table &var1.
    %if &var2. NE %str() %then 
     * &var2. ;
    %if &var3. NE %str()  %then 
    * &var3. ;
    / out= freq_&var1.&var2.&var3. norow nocol nopercent;
    %if &cond. NE %str() %then
    &cond.;
    ;
Run;

%mend;

%let dataset_full = sashelp.class;

%check(var1=age,var2=weight, cond=%str(where age=1 and weight=10));
2赞 Richard 11/2/2023 #2

如果您使用数据集 where= 选项并强制用户在括号表达式中传递条件(与 where= 要求的内容相同),宏将计算出它

例:

默认值将选择所有行。=(1)

%macro freq(data=,var1=,var2=,var3=,where=(1));

  proc freq noprint data=&data(where=&where);
    table &var1
    %if &var2. NE %str() %then 
       * &var2. ;
    %if &var3. NE %str()  %then 
      * &var3. ;
    / out="&var1._&var2._&var3." norow nocol nopercent;
      ;
  run;

%mend;

options mprint;

%freq(data=sashelp.cars, var1=type)
%freq(data=sashelp.cars, var3=enginesize, var1=type)
%freq(data=sashelp.cars, var2=origin, var3=drivetrain, var1=type)
%freq(data=sashelp.cars, var2=origin, var3=drivetrain, var1=type
     ,where=(origin='Asia' and drivetrain='All' and msrp<50000))
            ^.................................................^

评论

2赞 Quentin 11/2/2023
其中 1 触发了我最喜欢的音符之一:我认为那里有一点有趣的态度。就像他们不必说“显然”,而是把它扔进去好玩。WHERE 1 /* an obviously TRUE WHERE clause */
0赞 Tom 11/2/2023 #3

宏处理器的 %IF 语句可能有问题。

使用其他测试来检查参数是否已填充。

最简单的测试是寻找非零长度。此外,WHERE 语句并不关心你是否给它一个空条件,所以根本不需要测试 &COND。

proc freq noprint data=&data;
  table &var1
%if %length(&var2) %then * &var2 ;
%if %length(&var3) %then * &var3 ; 
    / out=&var1._&var2._&var3. norow nocol nopercent;
  ;
  where &cond ;
run;

如果变量名称的长度超过平均 10 个字节,则 OUT 数据集名称也可能有问题。