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