【问题标题】:SAS if statement in do loopdo循环中的SAS if语句
【发布时间】:2018-11-06 20:08:01
【问题描述】:

您好,我正在尝试使用 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.

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

【问题讨论】:

  • 这将有助于显示您的输入数据和预期输出。
  • 一般来说,如果你想将相同的过程应用于不同的变量,使用数组比使用宏更容易。
  • 数据是什么样的?变量pianopiano_1是什么意思?

标签: loops if-statement sas sas-macro


【解决方案1】:

宏变量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)

总之,在开始宏编码之前,请确保您的数据塑造和评估处理方法坚如磐石。如果您问自己我应该对此进行宏化吗?,请保守一点并回答“否”。对维护者和未来的自己友好,不要让事情变得过于复杂。

【讨论】:

  • 感谢您的回答!我确实对何时宏观化以及何时不宏观化感到困惑。我是 SAS 新手,我仍在学习它。非常感谢您的有益建议。
【解决方案2】:

您的代码需要进行一些调整,我做了一些更改。此外,当我们使用 %if 时,我们总是使用宏变量。否则,我们最好使用带有普通数据集变量的 if 语句。

%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;
   if missing(special_kid) then do;
      %do i=1 %to %sysfunc(countw(&instrm));
          %let word = %scan(&instrm, &i);
          %If &word ^=. and &word._1 ^=. %then %do;
          talent_type=1; type_name=&word._1;
          %end;
      %end;
  end;
run;
%mend my_func;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多