在 SAS 中使用部分关键字提取完整关键字

Using part of a keyword to extract a full keyword in SAS

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

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

这一行:

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

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

0;
1;

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

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

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

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

%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))。有关详细信息,请参阅
  • 你一直在比较每个单词的长度 (&&word_&i.) 与“年份”的位置 (&Keyword_loc.)。但是,你应该比较累计长度,你称之为size
  • 正如 Tom 在另一个答案中指出的那样,您有一个没有任何其他语句的 eval 函数。你可能想写 %let size = %eval(&size.+ &&word_&i. + 1);