首页 > 解决方案 > do循环中的SAS if语句

问题描述

您好我正在尝试使用 do 循环和 if 语句编写宏函数。我想我搞砸了 if-then do 和 do 循环,我无法找出问题所在。我有一张儿童信息表,其中包含年龄、性别、运动、乐器等列。

我的原始代码有效,如下所示:

data old;
   set new;
   if sports in ("football","basketball") and age <=7 then type =1;
      else if sports='swimming' then type=2;
   if special_kid=. then do;
     if piano ^=. and piano_1 ^=. then do; talent_type=1; type_name=piano_1; end;
     if violin ^=. and violin_1 ^=. then do; talent_type=1; type_name=violin_1; end;
   end;
 run;

我有一堆要编辑类型和名称的乐器。我想编写一个循环来自动执行此操作,但我不确定为什么下面的代码不起作用。

%let instrm = piano violin;
%macro my_func;
   data old;
   set new;
   %if sports in ("football","basketball") and age <=7 %then type =1;
      %else %if sports='swimming' %then type=2;
   %do %while (special_kid=.);
      %do i % to sysfunc(countw(&instrm));
          %let word = %scan(&name, &i);
          %if &word ^=. and ^word._1 ^=. %then %do;
          talent_type=1; type_name=&word._1;
          %end;
     %end;
  %end;
run;
%mend;

它不断给我错误

 ERROR: An unexpected semicolon occurred in the %DO statement.
 ERROR: A dummy macro will be compiled.

谁能回答我的问题?谢谢!

标签: loopsif-statementsassas-macro

解决方案


宏变量instrm实际上是一个包含以空格分隔的变量名称列表的值。您最好从特定的变量使用角色中抽象出来并回退到更通用的参数名称vars。此外,与其依赖在全局或包含范围内定义的宏变量,不如在调用期间传入列表。你是正确的,一个空格分隔的列表可以在宏中迭代一个%do循环,其上限是countw列表中“单词”的数量——你的语法只有一点点。

你不必宏观化一切,运动逻辑的额外宏观化走得很远。请记住,宏调用会发出(或生成)输入 SAS 提交系统的源代码。更抽象或工具箱时的宏编码编码过程有时称为codegen。

您的原始代码可能有问题,因为您评估(在一行中)多个特殊的孩子变量并对相同的 2 个变量(talent_typetype_name)执行值分配,因此可能会覆盖先前分配的值。有时,这样的评估和分配是OUTPUT分开的行。

%macro my_skill_classifier(data=, out=, special_vars=, special_type=);
   %local i var;

   data &out;
   set &data;

   if sports in ("football","basketball") and age <=7 then type = 1;
   else
   if sports='swimming' then type=2;

   * what happens to football/baskeball > 7yr ?;

   if missing(special_kid) then do;
      %do i = 1 %to sysfunc(countw(&special_vars));
        %let var = %scan(&special_vars, &i);

        * regular data step code with macro resolutions sprinkled in;
        if &var ^=. and var._1 ^=. then do; 
          talent_type = &special_type;
          type_name = &var._1;
          * maybe you really mean type_name = "&var._1";
        end;
      %end; %* end loop over special_vars list;
    end;
  run;
%mend;

%my_skill_classifier(data=new, out=old, special_vars=piano violin, special_type=1)

总而言之,在开始宏编码之前,请确保您的数据整形和评估处理方法是坚如磐石的。如果你问自己我应该宏这个吗?,保守一点,回答不。对维护者和未来的自己友好,不要让事情变得过于复杂。


推荐阅读