【问题标题】:Using part of a keyword to extract a full keyword in SAS在 SAS 中使用部分关键字提取完整关键字
【发布时间】:2020-11-04 22:22:27
【问题描述】:

在我的项目中,我接受用户输入,其中一个变量是提取的关键。这个变量是年份,但可以为某些数据集编写,例如“Graduation_year”,而在其他数据集中可能是“Year_of_purchase”等等。我需要做的是将此变量从列表中取出,以便与列表的其余部分分开使用。从下面的示例中,我想要的结果如下所示: 输入 -> (Gender Graduation_Year Course_Name) 输出 -> Var_of_importance = Graduation_year 和 Remainder_vars= Gender Course_name。

到目前为止,我使用的代码遇到了一个错误,因为我试图在称为 size 的第二个循环的每次迭代中更新一个宏变量。

代码如下:

%macro Year_finder(var_list);

%local size;
%Put The variables are: &var_list.;
%let Keyword_loc=%Index(&var_list.,Year);

%put The location of the keyword Year begins at place number &Keyword_loc.;

%do i=1 %to %sysfunc(countw(&var_list.));
    %let word_&i.=%length(%sysfunc(scan(&var_list.,&i.)));
    %put The length of %sysfunc(scan(&var_list.,&i.)) is &&word_&i.;
%end;

%do i=1 %to %sysfunc(countw(&var_list.));
    
    %if i=1 %then %do;
        %if &&word_&i. LT &Keyword_loc. and &&word_(&i.+1)+1 GT &Keyword_loc. %then Word = %sysfunc(scan(&var_list.,&i.));
        %let size=&&word_&i.;

        %put The step number is step &i.;
        %put The &i.th word has a length of &&word_&i.;
        %put Initial length is &size.;
    %end;
    
    %else %do;
        %eval(&size. = &size.+ &&word_&i. + 1);
        %if &size. LT &Keyword_loc. and &size. + &&word_(&i.+1) + 1 GT &Keyword_loc. %then Word = %sysfunc(scan(&var_list.,(&i.+1)))

        %put This step number is step &i.;
        %put The length variable = &size.;
        %put The word is &Word.;
    %end;
%end;

%mend;

%Year_finder(Gender Graduation_Year Course_Name);

目前这似乎会做我想做的事,但由于我无法克服这个错误,我无法验证它是否有效。任何帮助将不胜感激。谢谢。

【问题讨论】:

    标签: compiler-errors sas macros sas-macro


    【解决方案1】:

    这一行:

    %eval(&size. = &size.+ &&word_&i. + 1);
    

    正在生成无效的 SAS 语句。根据等号左侧和右侧的比较结果,它将生成这两个语句之一。

    0;
    1;
    

    我怀疑你要么想要某种 %LET 语句。

    %let size = %eval(&size.+ &&word_&i. + 1);
    

    或者,如果您确实打算使用宏生成可在另一个语句中间使用的 0 或 1,则不要在 %eval() 之后包含分号。

    【讨论】:

      【解决方案2】:

      要解决您的问题,最简单的方法是检查每个单词是否单独包含“年份”并将它们添加到所需的输出宏变量中。以下应该有效:

      %macro Year_finder(var_list);
      
         * Initialize output variables;
         %global Var_of_importance Remainder_vars;
         %let Var_of_importance = ;
         %let Remainder_vars = ; 
      
         * Go through words from var_list;
         %do i=1 %to %sysfunc(countw(&var_list.));
            * Add word to var_of_importance if it contain "year" (not case sensitive);
            %if %index(%lowcase(%scan(&var_list.,&i.)),year) %then %do;
               %let Var_of_importance = &Var_of_importance %scan(&var_list.,&i.);
            %end;
            %else %do;
               * Add word to Remainder_vars if it does not contain "year";
               %let Remainder_vars = &Remainder_vars %scan(&var_list.,&i.);
            %end;
         %end;
      
      %mend;
      
      %Year_finder(Gender Graduation_Year Course_Name);
      

      你的原始代码有几个问题

      • 您从未提及变量 Var_of_importance 或 Remainder_vars 是您的最终目标。请注意,这些应该是全局变量。
      • 您在第一个 if 语句中遗漏了一个 & 符号。将%if i=1 %then %do; 更改为%if &i=1 %then %do;
      • 在你的下一个 if 语句中缺少一个 %sysevalf() 来评估复杂的表达式,你在你的 %then word = 中缺少一个 %let
      • 如果你想引用下一个索引你不能写&&word_(&i.+1)。相反,您可以写%superq(word_%eval(&i+1))。详情见Resolving macro containing %eval in macro variable name, SAS
      • 您不断将每个单词的长度 (&&word_&i.) 与“年份”的位置 (&Keyword_loc.) 进行比较。但是,您应该比较累积长度,您称之为size
      • 您有一个没有任何其他语句的 eval 函数,正如 Tom 在另一个答案中所指出的那样。你可能想写%let size = %eval(&size.+ &&word_&i. + 1);

      【讨论】:

      • 感谢 Jeppe 的帮助。我仍然习惯了一些更难的宏功能,因此错过了它们的功能。你的回答很有帮助。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2022-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多