在 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);
在我的项目中,我正在接受用户输入,其中一个变量是提取的关键。这个变量是年份,但对于某些数据集可能会写成“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 =
中错过了一个 - 如果你想引用下一个索引你不能写
&&word_(&i.+1)
。相反,您可以写%superq(word_%eval(&i+1))
。有关详细信息,请参阅 - 你一直在比较每个单词的长度 (
&&word_&i.
) 与“年份”的位置 (&Keyword_loc.
)。但是,你应该比较累计长度,你称之为size
- 正如 Tom 在另一个答案中指出的那样,您有一个没有任何其他语句的 eval 函数。你可能想写
%let size = %eval(&size.+ &&word_&i. + 1);
%let