How to avoid macro %Do error in open code

Accepted Solution Solved
Reply
Contributor
Posts: 51
Accepted Solution

How to avoid macro %Do error in open code


Dear SAS community support,

I developed a sas program. It worked fine within a macro. But when I remove the macro definition and run the code in open, it generated the error.

%do %while (%scan(&var_list, &i, " ") ^=%str());

ERROR: The %DO statement is not valid in open code.

How do I avoid this error if I do not want to use macro ?

I attached the code as follows:

-----------------------------------------------------

data class; set sashelp.class; if ranuni(0) lt .5 then call missing(name,age);run;

proc datasets nodetail nolist;
  delete outfile3;
  run;


*%macro testit;   * do not use macro *;

proc format;
value $ missfmt ' '="Missing"
other="Not Missing" ;
value nmissfmt . ="Missing"
other="Not Missing" ;
run;

title 'List of variables ';
ods table variablesshort=varshort;
proc contents data=class short;
run;
 
data _null_;
set varshort;
call symput ("var_list", variables);
run;

proc sql noprint;
  *Get count of total number of observations into macro variable;
  select count(*) into : obs_count from class;
quit;

*Start looping through the variable list here;

%let i=1;
%do %while (%scan(&var_list, &i, " ") ^=%str());
%let var=%scan(&var_list, &i, " ");  

*Get count of missing;
proc freq data=class noprint;
    table &var/missing out=cross_tab1;
    format _character_ $missfmt. _numeric_ nmissfmt.;
run;

*Get format of missing;
data _null_;
set cross_tab1;
call symput("var_fmt", vformat(&var));
call symput("var_label", vlabel(&var));
run;

data cross_tab2;
    set cross_tab1;
    length variable $50.;
    category=put(&var, &var_fmt.);
    variable="&var_label.";
    if _n_=1 and category='Not Missing' then do;
        Number_Missing=&obs_count-count;
        Number_Existing = count;  
        Percent_Missing = Number_Missing/&obs_count. ;   
        Percent_existing = 1 - Percent_Missing;
        percent=percent/100;
        output;
    end;
    else if _n_=1 and category='Missing' then do;
        Number_Missing=count;  
        Number_existing=&obs_count - count;  
        Percent_Missing = percent/100; 
        Percent_existing= 1 - Percent_Missing;
        output;
    end;
        format percent: percent10.1;
    Keep variable Number_Missing Number_existing Percent_Missing Percent_existing;
run;
proc append base=outfile3 data=cross_tab2 force;
run;
*Increment counter;
%let i=%eval(&i+1);
%end; *Categorical;
*%mend;

*%testit

proc print data=outfile3; title 'outfile3 data'; run;

---------------------------------------------------------------

Thanks for your support.

Regards,

William


Accepted Solutions
Solution
‎06-29-2015 12:42 PM
Super User
Super User
Posts: 6,326

Re: How to avoid macro %Do error in open code

Just have PROC FREQ generate all of the frequencies in one step.

I leave the reformatting of the data as any exercise.

* Create some sample data with some missing values ;

data class; set sashelp.class; if ranuni(0) lt .5 then call missing(name,age);run;

* Create formats ;

proc format;

value $ missfmt ' '="Missing"

other="Not Missing" ;

value nmissfmt . ="Missing"

other="Not Missing" ;

run;

* Generate frequencies ;

ods output onewayfreqs=freqout;

ods listing off;

proc freq data=class;

tables _all_ / missing;

format _character_ $missfmt. _numeric_ nmissfmt. ;

run;

ods listing;

* Restructure frequencies ;

data want ;

  length var $32 fvalue $50 ;

  set freqout;

  var=scan(table,-1);

  fvalue=vvaluex('F_'||var);

  keep var fvalue frequency percent;

run;

proc print width=min; run;


SAS 9.4 on WINDOWS

Obs    var       fvalue         Frequency    Percent

1     Name      Missing           11         57.89

2     Name      Not Missing        8         42.11

3     Sex       Not Missing       19        100.00

4     Age       Missing           11         57.89

5     Age       Not Missing        8         42.11

6     Height    Not Missing       19        100.00

7     Weight    Not Missing       19        100.00

View solution in original post


All Replies
Valued Guide
Posts: 3,206

Re: How to avoid macro %Do error in open code

Redesign the design using a complete different technique.

This one was started to use macro from start.

---->-- ja karman --<-----
Respected Advisor
Posts: 4,973

Re: How to avoid macro %Do error in open code

William,

Your choices are limited if you want to simulate a %DO statement outside of a macro definition.  A DATA step can do the trick, either using CALL EXECUTE or using PUT statements to write your program out to a file.  Due to the length of your code, and the relative ease of debugging, I would recommend the second approach.  Here's the outline.

filename somefile 'path to a file';

data _null_;

   length next_var $ 32;

   file somefile noprint; 

   do _i_=1 to countw("&var_list");
      next_var = scan("&var_list", _i_);

      *** Use PUT statements to write out a complete set of SAS steps that need to occur for each variable;

   end;

   stop;

run;

%include somefile;

Note that you may look at this and decide that it's easier to write a macro that permits %DO.  And there are some SAS steps that don't need to be repeated every time through the loop such as PROC FORMAT.

Good luck.

Grand Advisor
Posts: 17,338

Re: How to avoid macro %Do error in open code

wtien196838 wrote:

I developed a sas program.

William

What's wrong with my code?

Contributor
Posts: 51

Re: How to avoid macro %Do error in open code

Reeza

Your code are correct and  I modified it a little bit.

Since you are the author of this macro, can you suggest any method to solve the %Do statement if I do not want to use macro to run it.

Thank you for sharing your knowledge.

William

Grand Advisor
Posts: 17,338

Re: How to avoid macro %Do error in open code

You can't - the basis of that code requires a macro loop. I wrote that code 4 years ago and threw it on GitHub for storage mostly.

Today, I would use a method similar to Tom's or I would transpose the data so I had all numeric in one column/dataset and all character in a second column/data set and then summarize. This method would allow me to obtain the variable labels as well, though again there are other ways to do that using SASHELP.VCOLUMN for example.

Solution
‎06-29-2015 12:42 PM
Super User
Super User
Posts: 6,326

Re: How to avoid macro %Do error in open code

Just have PROC FREQ generate all of the frequencies in one step.

I leave the reformatting of the data as any exercise.

* Create some sample data with some missing values ;

data class; set sashelp.class; if ranuni(0) lt .5 then call missing(name,age);run;

* Create formats ;

proc format;

value $ missfmt ' '="Missing"

other="Not Missing" ;

value nmissfmt . ="Missing"

other="Not Missing" ;

run;

* Generate frequencies ;

ods output onewayfreqs=freqout;

ods listing off;

proc freq data=class;

tables _all_ / missing;

format _character_ $missfmt. _numeric_ nmissfmt. ;

run;

ods listing;

* Restructure frequencies ;

data want ;

  length var $32 fvalue $50 ;

  set freqout;

  var=scan(table,-1);

  fvalue=vvaluex('F_'||var);

  keep var fvalue frequency percent;

run;

proc print width=min; run;


SAS 9.4 on WINDOWS

Obs    var       fvalue         Frequency    Percent

1     Name      Missing           11         57.89

2     Name      Not Missing        8         42.11

3     Sex       Not Missing       19        100.00

4     Age       Missing           11         57.89

5     Age       Not Missing        8         42.11

6     Height    Not Missing       19        100.00

7     Weight    Not Missing       19        100.00

Contributor
Posts: 51

Re: How to avoid macro %Do error in open code

Thanks for all contributors.

I applied Tom's code. Split two data sets Missing and Non Missing. Then merge back by variables to get the result I want.

Again I appreciate to all helpful hands.

Regards

William

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 7 replies
  • 1014 views
  • 8 likes
  • 5 in conversation