英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论