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

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

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

问题

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

%MACRO RegRepeat ; 

    %global maxVIFvar ;      /* maxVIFvar: 全局符号表 */ 
	%global maxVIFval ;      /* maxVIFval: 全局符号表 */ 
	%global j ;              /*     j    : 全局符号表 */ 
	%let maxVIFval = 10000 ;  
	%let j = 1 ;             
	
	%do %WHILE(  &maxVIFval > 1000  ) ; 
	   
	    /* 下面是回归过程 */
	    PROC REG DATA=KNHANES.HNAP1319 ; 
		    TITLE ; 
		    TITLE "最大VIF值:&maxVIFval / 重复次数:&j" ; 
			WEIGHT wt_pft_pool ; 
			WHERE HE_COPD = 3 ; 
			MODEL HE_fev1_new = SEX_new AGE OBE INCM_LH DJ4_dg_new sm1_former sm1_current at_risk_occp
			                    &airPollution / 缺乏拟合 ADJRSQ VIF  ; 
			ods output ParameterEstimates = PE ;
		RUN ; 
		
		/* 下面是SQL过程 */
		PROC SQL ;
		    CREATE TABLE WORK.maxVIF AS
		    SELECT Variable, max(VarianceInflation) AS maxVIF
		    FROM WORK.PE
		    HAVING VarianceInflation = MAX(VarianceInflation) ; 
		QUIT ;
	
	    /* 下面是DATA步骤 */
		DATA WORK.maxVIFtoMV ;
			SET WORK.maxVIF ; 
			CALL SYMPUT("maxVIFvar", VARIABLE); 
			CALL SYMPUT("maxVIFval", maxVIF); 
		RUN ; 
		
		%let airPollution = %sysfunc(tranwrd(&airPollution, &maxVIFvar, )) ;
	    %let j = %eval(&j+1) ;     
		%PUT 最大VIF值:&maxVIFval / 重复次数:&j ; 
   
	%end ;
	
%MEND ;

%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.

%MACRO RegRepeat ; 

    %global maxVIFvar ;      /* maxVIFvar: global symbol table */ 
	%global maxVIFval ;      /* maxVIFval: global symbol table */ 
	%global j ;              /*     j    : global symbol table */ 
	%let maxVIFval = 10000 ;  
	%let j = 1 ;             
	
	%do %WHILE(  &maxVIFval > 1000  ) ; 
	   
	    /* Regression procedure below */
	    PROC REG DATA=KNHANES.HNAP1319 ; 
		    TITLE ; 
		    TITLE "MAX VIF: &maxVIFval / Repeated Number: &j" ; 
			WEIGHT wt_pft_pool ; 
			WHERE HE_COPD = 3 ; 
			MODEL HE_fev1_new = SEX_new AGE OBE INCM_LH DJ4_dg_new sm1_former sm1_current at_risk_occp
			                    &airPollution / lackfit ADJRSQ VIF  ; 
			ods output ParameterEstimates = PE ;
		RUN ; 
		
		/* SQL procedure below */
		PROC SQL ;
		    CREATE TABLE WORK.maxVIF AS
		    SELECT Variable, max(VarianceInflation) AS maxVIF
		    FROM WORK.PE
		    HAVING VarianceInflation = MAX(VarianceInflation) ; 
		QUIT ;
	
	    /* DATA Step below */
		DATA WORK.maxVIFtoMV ;
			SET WORK.maxVIF ; 
			CALL SYMPUT("maxVIFvar", VARIABLE); 
			CALL SYMPUT("maxVIFval", maxVIF); 
		RUN ; 
		
		%let airPollution = %sysfunc(tranwrd(&airPollution, &maxVIFvar, )) ;
	    %let j = %eval(&j+1) ;     
		%PUT MAX VIF: &maxVIFval / Repeated Number: &j ; 
   
	%end ;
	
%MEND ;

%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将宏中的数字视为字符:

%if 696.59402283>1000 %then %do;
  %put 0;
%end;
%else %do;
  %put 1;
%end;

0

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

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

%if 696>1000 %then %do;
  %put 0;
%end;
%else %do;
  %put 1;
%end;

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:

%if 696.59402283>1000 %then %do;
  %put 0;
%end;
%else %do;
  %put 1;
%end;

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:

%if 696>1000 %then %do;
  %put 0;
%end;
%else %do;
  %put 1;
%end;

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:

确定