Julia Hansen
Julia Hansen

Reputation: 13

In SAS, is there a way to run multiple proc freqs with different formats in a macro?

I want to run proc freqs with multiple tables for a large amount of variables, looking at each variable by demographics - gender, race, education, etc.. Instead of writing these by hand, I want to create a macro that will allow me to do this. The problem I have is that in the proc freq statement, each variable has a different format that I want to use, and I can't figure out how to accomplish this.

My code looks like this (with more variables):

%let variables = care hours primary;
%let variableforms = caref hoursf primaryf;

%macro mymacro;
%let i = 1;
%let var = %scan(&variables,&i);
%let varform = %scan(&variableforms, &i);

%do %while(%length(&var) > 0);

proc surveyfreq data=mydata;
tables &var;
tables gender*&var;
tables race*&var;
tables education*&var;
tables income*&var;
format &var &varform. gender genderf. race racef. education educationf. income incomef.;
run;

%let i = %eval(&i + 1);
%let var = %scan(&variables, &i);
%let varform = %scan(&variableforms, &i);
%end;
%mend;

%mymacro;

But I get warnings that the "variables" caref, hoursf, and primaryf aren't found in my data, and the formats are not applied. If I can't directly call the formats in a let statement, is there a way for me to do this?

Upvotes: 1

Views: 51

Answers (2)

Tom
Tom

Reputation: 51621

Just include the full format specification in the list, not just the NAME of the format. The period is not always at the end of the format specification.

%let variables = care hours date;
%let variableforms = caref. 5.1 monyy7.;

Make sure to tell %SCAN() you only want to use space as the delimiter. If you don't tell %SCAN() what delimiters to use the default list will include period.

%let var = %scan(&variables,&i,%str( ));

You can always make the macro smart enough to append a period only when one does not exist. Remember that a period at the end of a macro variable reference is used to indicate the end of the macro variable name. This allows you to append letters or digits without the macro processor thinking they are part of the name. So add a second period that will become part of the value.

%if not %index(&varform,.) %then %let varform=&varform..;

So try something like this:

%macro mymacro(variables,variableforms);
%local i var varform;
proc surveyfreq data=mydata;
  format gender genderf. race racef. education educationf. income incomef.;

%do i=1 %to %sysfunc(countw(&variables,%str( )));
  %let var = %scan(&variables,&i,%str( ));
  %let varform = %scan(&variableforms,&i,%str( ));
  %if not %index(&varform,.) %then %let varform=&varform..;
  tables &var (gender race education income)*&var;
  format &var. &varform. ;
%end;

run;
%mend;

%mymacro
(variables = care hours primary
,variableforms = caref. hoursf primaryf
)

Upvotes: 2

PBulls
PBulls

Reputation: 1731

Macro resolution gobbles up a trailing period, you'll want &varform...

Otherwise the first iteration will result in format care caref gender genderf. [..], which will take the first three entries as variables to receive the format genderf..

Upvotes: 2

Related Questions