为什么我的 %DO %UNTIL 循环在 SAS 宏程序中条件未满足的情况下仍然执行?

huangapple go评论79阅读模式
英文:

Why is my %DO %UNTIL loop implemented even though the loop not satisfied the conditions in SAS MACRO PROGRAM?

问题

这是您的SAS宏程序代码的翻译部分:

  1. %MACRO RegRepeat ;
  2. %global maxVIFvar ; /* maxVIFvar: 全局符号表 */
  3. %global maxVIFval ; /* maxVIFval: 全局符号表 */
  4. %global j ; /* j : 全局符号表 */
  5. %let maxVIFval = 10000 ;
  6. %let j = 1 ;
  7. %do %WHILE( &maxVIFval > 1000 ) ;
  8. /* 下面是回归过程 */
  9. PROC REG DATA=KNHANES.HNAP1319 ;
  10. TITLE ;
  11. TITLE "最大VIF值:&maxVIFval / 重复次数:&j" ;
  12. WEIGHT wt_pft_pool ;
  13. WHERE HE_COPD = 3 ;
  14. MODEL HE_fev1_new = SEX_new AGE OBE INCM_LH DJ4_dg_new sm1_former sm1_current at_risk_occp
  15. &airPollution / 缺乏拟合 ADJRSQ VIF ;
  16. ods output ParameterEstimates = PE ;
  17. RUN ;
  18. /* 下面是SQL过程 */
  19. PROC SQL ;
  20. CREATE TABLE WORK.maxVIF AS
  21. SELECT Variable, max(VarianceInflation) AS maxVIF
  22. FROM WORK.PE
  23. HAVING VarianceInflation = MAX(VarianceInflation) ;
  24. QUIT ;
  25. /* 下面是DATA步骤 */
  26. DATA WORK.maxVIFtoMV ;
  27. SET WORK.maxVIF ;
  28. CALL SYMPUT("maxVIFvar", VARIABLE);
  29. CALL SYMPUT("maxVIFval", maxVIF);
  30. RUN ;
  31. %let airPollution = %sysfunc(tranwrd(&airPollution, &maxVIFvar, )) ;
  32. %let j = %eval(&j+1) ;
  33. %PUT 最大VIF值:&maxVIFval / 重复次数:&j ;
  34. %end ;
  35. %MEND ;
  36. %RegRepeat

希望这能帮助您理解您的SAS宏程序代码。

英文:

I wrote the following SAS macro program code.

The purpose of the code is to repeat PROCREG while the condition(&maxVIFval > 1000) is satisfied.

However the %DO %WHILE loop is executed continually even though &maxVIFval has a value of 1000 or less.

I wonder what the reason is.

I'm looking for help..

Forgive my poor English.

  1. %MACRO RegRepeat ;
  2. %global maxVIFvar ; /* maxVIFvar: global symbol table */
  3. %global maxVIFval ; /* maxVIFval: global symbol table */
  4. %global j ; /* j : global symbol table */
  5. %let maxVIFval = 10000 ;
  6. %let j = 1 ;
  7. %do %WHILE( &maxVIFval > 1000 ) ;
  8. /* Regression procedure below */
  9. PROC REG DATA=KNHANES.HNAP1319 ;
  10. TITLE ;
  11. TITLE "MAX VIF: &maxVIFval / Repeated Number: &j" ;
  12. WEIGHT wt_pft_pool ;
  13. WHERE HE_COPD = 3 ;
  14. MODEL HE_fev1_new = SEX_new AGE OBE INCM_LH DJ4_dg_new sm1_former sm1_current at_risk_occp
  15. &airPollution / lackfit ADJRSQ VIF ;
  16. ods output ParameterEstimates = PE ;
  17. RUN ;
  18. /* SQL procedure below */
  19. PROC SQL ;
  20. CREATE TABLE WORK.maxVIF AS
  21. SELECT Variable, max(VarianceInflation) AS maxVIF
  22. FROM WORK.PE
  23. HAVING VarianceInflation = MAX(VarianceInflation) ;
  24. QUIT ;
  25. /* DATA Step below */
  26. DATA WORK.maxVIFtoMV ;
  27. SET WORK.maxVIF ;
  28. CALL SYMPUT("maxVIFvar", VARIABLE);
  29. CALL SYMPUT("maxVIFval", maxVIF);
  30. RUN ;
  31. %let airPollution = %sysfunc(tranwrd(&airPollution, &maxVIFvar, )) ;
  32. %let j = %eval(&j+1) ;
  33. %PUT MAX VIF: &maxVIFval / Repeated Number: &j ;
  34. %end ;
  35. %MEND ;
  36. %RegRepeat

These are sentences from the log window.

MPRINT(REGREPEAT): TITLE "MAX VIF: 10000 / Repeated Number: 1" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 1588.907368 / Repeated Number: 2" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 1297.8441436 / Repeated Number: 3" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 696.59402283 / Repeated Number: 4" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 569.83744288 / Repeated Number: 5" ;

Please let me know if you need any additional information.

Thank you for your kindness.

答案1

得分: 2

为了解决这个问题,使用%sysevalf(&maxVIFval > 1000)代替&maxVIFval > 1000

当SAS在宏中比较两个数字时,当数字包含小数点和不包含小数点时,SAS有不同的规则。当存在小数点时,SAS将宏中的数字视为字符:

  1. %if 696.59402283>1000 %then %do;
  2. %put 0;
  3. %end;
  4. %else %do;
  5. %put 1;
  6. %end;
  7. 0

SAS在比较字符时,从左到右逐个字符进行比较,“6”在ASCII码序列中大于“1”,因此我们有 696.59402283>1000

当没有小数点时,SAS将宏中的数字视为数字:

  1. %if 696>1000 %then %do;
  2. %put 0;
  3. %end;
  4. %else %do;
  5. %put 1;
  6. %end;
  7. 1

比较是基于数学规则进行的。

我建议您在宏中进行数字比较时始终使用%sysevalf()函数,除非您百分之百确定没有小数点。

英文:

To fix this issue, use %sysevalf(&maxVIFval > 1000) to instead of &maxVIFval > 1000.

When SAS compares two numbers in macro, it has different rules when numbers contain decimal point or not. When there is a decimal point, SAS treats numbers in macro as characters:

  1. %if 696.59402283>1000 %then %do;
  2. %put 0;
  3. %end;
  4. %else %do;
  5. %put 1;
  6. %end;
  7. 0

SAS compares characters char by char from left to right when comparing characters, "6" is larger than "1" in ascii code sequence, so we have 696.59402283>1000.

When there are no decimal points, SAS treats numbers in macro as numbers:

  1. %if 696>1000 %then %do;
  2. %put 0;
  3. %end;
  4. %else %do;
  5. %put 1;
  6. %end;
  7. 1

The comparsion is based on mathmatical rules.

I sugguest you always use %sysevalf() function if you want to do number comparsion in macro, unless you are 100% sure there are no decimal points.

huangapple
  • 本文由 发表于 2023年2月14日 09:31:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75442702.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定