BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
cuicui
Calcite | Level 5

I want to create a backward selection of a glimmix model, but there is a error about the macro word "end", please tell me what should i do? thanks a lot !

this is the part of the programme.

255  /*-------------------------back ward-----exclude the variable with probF>exclude------------------------------------------  */

256                      /*run model with all selected variabels */

257                %do %while (&stop=0);

258                    %let j = %eval(&j+1);

259                    ods output Tests3=Testsb(keep=effect ProbF);

260                    proc glimmix data=&table

261                         method=&method;

262                         &class;

263                         model &varcible (event='1')=&varselec / solution dist=binary

263! link=logit oddsratio ;

264                               &random;

265                        nloptions maxiter=100;

266                    run;

267

268                    /*we remove the worst variable thanks to the p value*/

269                    data  Testsb; set Testsb; nobis=1; call symput('num',nobis);run;

270                    %if &stop=0 %then %do;

271                        proc sort data=Testsb; by descending ProbF; run;

272                        data apport1; set Testsb; by nobis ; if first.nobis; run;

273                        data fsd1;  set apport1; retain stopper 0;

274                          if first.ProbF>&exclude then

275                              stopper=1;

276                              call symput('var1',effect);

277                              varselec1=compress(&varselec,"&var1","t");

277! /*删除无意义的变量*/

278                              call symput('varselec1',varselec1);

279                              call symput('stop',stopper);

280                        run;

281                     %end;

282                     %if &stop=1 and &notconv=0 %then %do;

283                         %put "Algorithm tell us to stop removing for new variables in

283! the model";

284                         %put "Last variable proposed to be remove was &var with a

284! p-value of &thres";

285                         %let  varselec=&varselec1;

286                     %end;

ERROR: Macro keyword END appears as text.

ERROR: A dummy macro will be compiled.

287                     %if &stop=0 and &notconv=0 %then %do;

288                         %put "Algorithm tell us to continue finding new variables for

288! the model";

289                         %let varselec=&varselec;

290                         %put "The variable dropped is &newvar";

291                    %end;

1 ACCEPTED SOLUTION

Accepted Solutions
art297
Opal | Level 21

What are you trying to accomplish with the following code:

data testsb;

  set Testsb;

  nobis=1;

  call symput('num',nobis);

run;

proc sort data=Testsb;

  by descending ProbF;

run;

data apport1;

  set Testsb;

  by nobis ;

  if first.nobis;

run;

data fsd1;

  set apport1;

  retain stopper 0;

  if first.ProbF>&exclude then  stopper=1;

  call symput('var1',effect);

  varselec1=compress(&varselec,"&var1","t");   /*delete the nonsignificant variable */

  call symput('varselec1',varselec1);

  call symput('stop',stopper);

run;

It wouldn't run, as is, because in the final data step you are using first.ProbF without including a by statement.

However, rather than offering a fix for that, it would be helpful to know what you are trying to accomplish in that section of code.  Are you trying to eliminate just one variable from your variable list?  Or all non-significant variables?

In either case, I would use a different approach.  I don't see any conflicts in your current variable names, but you could easily hit a situation where removing a variable name might also be removing part of another variable's name.

Instead, based upon what you are trying to do, I'd suggest something like:

%let threshold=0.05;

/*create some test data*/

data Testsb;

  informat effect $15.;

  input effect ProbF;

  cards;

sex .01

tion .05

agegroup4 .06

cityprop1 .07

education2 .02

marriage .08

medinsure1 .1

Income1 .003

clear .004

service .05

BMI .07

roomnum_person .0001

area_person .0005

;

/*if you only want to drop the most non-significant variable*/

proc sort data=Testsb;

  by descending ProbF;

run;

data Testsb;

  set Testsb;

  if _n_ eq 1 and ProbF le &Threshold. or _n_ gt 1 then output;

run;

proc sql noprint;

  select effect

    into :varselec1 separated by " "

      from Testsb

  ;

quit;

/*or, if you want to drop all non-significant variables*/

proc sql noprint;

  select effect

    into :varselec1 separated by " "

      from Testsb

        where ProbF le &Threshold.

  ;

quit;

View solution in original post

8 REPLIES 8
art297
Opal | Level 21

You will probably have to post your entire macro in order for anyone to be able to see what the problem might be.

Have you tried to run it after running:

options mprint mlogic symbolgen;

?

That will provide more info as to what is going on.

I saw two thing which may be incorrect and causing the problem.  In your use of proc glimmix you have one statement that simply reads: &class;

Was that supposed to be class &class.;

or was the string "class" already part of the macro variable?

Also, just under that, you have a statement that starts with model &varcible

Odd looking macro variable name.  Was that the correct name, or a typo?

cuicui
Calcite | Level 5

thanks a lot for your suggestions, the reason is the wrong compelling of the code, but there is another error "

ERROR 72-185: The COMPRESS function call has too many arguments.."

there is the error in the "backward" section, that is "compress(&varselec,"&var1","t");", please tell m whats wrong with this section, thanks a lot !

there is the entire programme


/*varlist--the selected varibale;varcible--the binary response variable (0/1);  method = RSPL*/
%macro stepwise(table=,method=,varlist=,varcible=,threshold=,exclude=,type==,random=,include=,varclass=);
   /*we declare some local variables*/
   %let varselec=;
   %let notconv=0;
   %let stop=0;
   %let j=0;

   %let random1=%str(random intercept / subject=&random solution type=&type;);
   %let class=%str(class &random &varclass;);   /*varclass  is the variables of class */

   /*FIRST APPROCH FORWARD  WE ADD ONE VARIABLE BY STEP*/
   /*We do a loop corresponding at each step of variables selection*/
          %do %while (&stop=0) ;
        %let j=%eval(&j+1);
        %put "STEP &j";
       
                   /* create a empty table */
      data tested_var;
         format effect $50. ProbF 4.3;
                  run;
                  %local i var;
                  %let i=0;
                  /*keep one by one variables which remain to test*/ 
                  %do %while(%scan(&varlist,&i+1,%str( )) ne %str( ));

                       %let i = %eval(&i+1);      
                      %let var=%scan(&varlist,&i,%str( ));
                       /* &varselec : variables already selected in the model
                             &var   : variables which remain to test */
       ods output Tests3=Tests3(keep=effect ProbF) ;
       title "Model with the variable &i";
       proc glimmix data=&table method=&method;
            &class;
         model &varcible(event='1')=&varselec &var/ solution   oddsratio  link=logit dist=binomial ;
         &random1;
         nloptions maxiter=100;
                       run;
        ods output off;


                       /*keep the P of new variable to test */
        data  Tests3; set Tests3; nobis=1; run;
        data  Tests3; set Tests3; if last.nobis; by nobis; run;
        data  tested_var; 
                             set tested_var Tests3;
                       run;

                     %end;
       

                 /*we keep the highest P value and then compare it to the threshold (0.05)-----forward*/
                 data gtgt; set tested_var;  if  ProbF=. then delete; run;
           proc sort data=gtgt; by ProbF; run;
           data apport; set gtgt; by nobis; if first.nobis; run;

           data fsd;  set apport; retain stopper 0;
                if ProbF>&threshold then stopper=1;  else stopper=0;
           call symput('stop',stopper);  

                    call symput('var',effect);
                    call symput('thres',ProbF);
                 run;
          %if &stop=1 %then %do;
                    %put "Algorithm tell us to stop looking for new variables in the model";
                    %put "Last variable proposed to be add was &var with a p-value of &thres";
               %end;
         %else %do;
              %put "Algorithm tell us to continue ";
                    %let  newvar=&var;
                    %put "The new variable is &newvar";
           %let  varselec=&varselec &newvar;

                    %put "Variables selected at step &j are &varselec";


/*-------------------------back ward-----exclude the variable with probF> exclude------------------------------------------  */
     /*run model with all selected variabels */
     %let stop2=0;
              %do %while (&stop2=0);
                  %let j = %eval(&j+1);
                  ods output Tests3=Testsb(keep=effect ProbF);
                  proc glimmix data=&table
                       method=&method;
                       &class;
                       model &varcible (event='1')=&varselec / solution dist=binary link=logit oddsratio ;
                             &random1;
                      nloptions maxiter=100;
                  run;

      /*we remove the worst variable thanks to the p value*/
      %let var1=;
                  %let varselec1=;
      data  Testsb; set Testsb; nobis=1; call symput('num',nobis);run;
      %if &stop2=0 %then %do;
                      proc sort data=Testsb; by descending ProbF; run;
       data apport1; set Testsb; by nobis ; if first.nobis; run;
                data fsd1;  set apport1; retain stopper 0;
                        if first.ProbF>&exclude then  stopper=1;
                            call symput('var1',effect);
       varselec1=compress(&varselec,"&var1","t");   /*delete the nonsignificant variable */
       call symput('varselec1',varselec1);
                  call symput('stop',stopper);
       run;
                   %end;
                   %if &stop=1 and &notconv=0 %then %do;
           %let stop2=1;
                       %put "Algorithm tell us to stop removing for new variables in the model";
                       %put "Last variable proposed to be remove was &var with a p-value of &thres";
                       %let  varselec=&varselec1;
                   %end;
                   %if &stop=0 and &notconv=0 %then %do;
           %let stop2=1;
                       %put "Algorithm tell us to continue finding new variables for the model";
                       %let varselec=&varselec;
                       %put "The variable dropped is &var1";
      %end;
  %end;

                   /*return to the forward  */
                  /*part to give us the list of variables which remain to test at the next step j+1*/
                  %let varenplus=;
                  %let i=0;
                  %do %while(%scan(&varlist,&i+1,%str( )) ne %str( )); 
                      %let i = %eval(&i+1);  
                      %let variable= %scan(&varlist,&i,%str( )); 
                      %if &variable ne &newvar %then %do;
                          %let varselection=1;
                      %end;
                      %else %do;
                          %let varselection=0;
                     %end;
                     %if &varselection=1 %then %do;
                        %let varenplus= &varenplus &variable ;
                     %end;
                 %end;
     /*New list of variables to test at the next step*/
                 %let varlist=&varenplus;
                 %put "Variables to test at the next step are &varlist";
           %end;
       %end;
    
/*final model */
ods output solutionR=solutionR
           OddsRatios=OddsRatios(KEEP=ESTIMATE DF LOWER UPPER)
     Tests3=TESTS(keep=df effect probF) ;
proc glimmix data=&table method=&method;
    &class;
model &varcible(event='1')=&varselec /
       solution oddsratio  link=logit dist=binomial ;
    &random1;
nloptions maxiter=100;
run;
%mend stepwise;

/*varlist--the selected variable ;varcible--binary response variable (0/1);method= RSPL*/
/*%macro stepwise(table=,n=,method=,varlist=,varcible=,threshold=,exclude=,type==,random=,include=,varclass=);*/
/*City sex tion agegroup4 cityprop1 education2 marriage medinsure1 Income1 clear service BMI roomnum_person area_person,*/

%stepwise(table=sasuser.new2,method=RSPL,varlist=sex tion agegroup4 cityprop1 education2 marriage medinsure1 Income1 clear service BMI roomnum_person area_person,
varcible=ill2,threshold=0.05,exclude=0.1,type=un,random=city,include=,varclass=sex tion agegroup4 cityprop1 education2 marriage medinsure1 Income1 clear service);

Tom
Super User Tom
Super User

This piece of code looks wrong to me.

       call symput('var1',effect);

       varselec1=compress(&varselec,"&var1","t");   /*delete the nonsignificant variable */


There are two problems.

1) It looks as  if you are expecting the second line to use the macro variable created in the first line.  But since the data step code is compiled before running the value of &VAR1 used in the second line will have already been determined before the data step starts. If you wanted to use the value of data step variable EFFECT then use it.

2) Compress does not remove words, it removes characters.  So if effect=SEX then it would remove all of the letters S, E and X.

Replace it with this and carefully examine the rest of the code to see if you have similar issues elsewhere.


       call symputX('var1',effect);

       varselec1=tranwrd(&varselec,effect,' ');   /*delete the nonsignificant variable */


cuicui
Calcite | Level 5

thanks,but there is similar error "ERROR 72-185: The TRANWRD function call has too many arguments."


art297
Opal | Level 21

What are you trying to accomplish with the following code:

data testsb;

  set Testsb;

  nobis=1;

  call symput('num',nobis);

run;

proc sort data=Testsb;

  by descending ProbF;

run;

data apport1;

  set Testsb;

  by nobis ;

  if first.nobis;

run;

data fsd1;

  set apport1;

  retain stopper 0;

  if first.ProbF>&exclude then  stopper=1;

  call symput('var1',effect);

  varselec1=compress(&varselec,"&var1","t");   /*delete the nonsignificant variable */

  call symput('varselec1',varselec1);

  call symput('stop',stopper);

run;

It wouldn't run, as is, because in the final data step you are using first.ProbF without including a by statement.

However, rather than offering a fix for that, it would be helpful to know what you are trying to accomplish in that section of code.  Are you trying to eliminate just one variable from your variable list?  Or all non-significant variables?

In either case, I would use a different approach.  I don't see any conflicts in your current variable names, but you could easily hit a situation where removing a variable name might also be removing part of another variable's name.

Instead, based upon what you are trying to do, I'd suggest something like:

%let threshold=0.05;

/*create some test data*/

data Testsb;

  informat effect $15.;

  input effect ProbF;

  cards;

sex .01

tion .05

agegroup4 .06

cityprop1 .07

education2 .02

marriage .08

medinsure1 .1

Income1 .003

clear .004

service .05

BMI .07

roomnum_person .0001

area_person .0005

;

/*if you only want to drop the most non-significant variable*/

proc sort data=Testsb;

  by descending ProbF;

run;

data Testsb;

  set Testsb;

  if _n_ eq 1 and ProbF le &Threshold. or _n_ gt 1 then output;

run;

proc sql noprint;

  select effect

    into :varselec1 separated by " "

      from Testsb

  ;

quit;

/*or, if you want to drop all non-significant variables*/

proc sql noprint;

  select effect

    into :varselec1 separated by " "

      from Testsb

        where ProbF le &Threshold.

  ;

quit;

Tom
Super User Tom
Super User

Most likely the macro variable VARSELEC has comma's in it.  For example of VARSELEC=a,c then

tranwrd(&varselec,effect,' ');

will become

tranwrd(a,b,effect,' ');


Which clearly has too many arguments.


As I asked before are you sure you want to reference a macro variable here?  Isn't the list of variables to select in an actual variable. Also if your list is comma delimited instead a more normal SAS construct of space delimited then using TRANWRD to eliminate a particular variable name will not work well.  In fact it will also not work well when the variable name you want to eliminate is a subset of another variable name.

cuicui
Calcite | Level 5

THANKS, BUT  I'm sure that the VARSELECT don't have commas in it, but like this "Education Sex City Imcom"

cuicui
Calcite | Level 5

the problem has been solved, thanks all of you, very much!Smiley Happy

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 8 replies
  • 6103 views
  • 6 likes
  • 3 in conversation