I need to run over 30 univariate logistic regression models. I want to make these codes using macro but whatever I do, it didn't produce the summary. Can someone please help me?
Non-macro code:
%macro univariate_logistic(data=, event=, vars=, class_vars=);
/* Create a temporary table to store results */
data _null_;
length var_name $20;
run;
/* Check if there are any class variables */
%let has_class_vars = %length(&class_vars);
%if &has_class_vars > 0 %then %do;
/* Run logistic regression for categorical variables */
%do i = 1 %to %sysfunc(countw(&class_vars));
%let var = %scan(&class_vars, &i);
proc logistic data=&data;
class &var / param=ref ref=last;
model &event (event='1') = &var;
run;
%end;
%end;
/* Run logistic regression for continuous variables */
%do i = 1 %to %sysfunc(countw(&vars));
%let var = %scan(&vars, &i);
proc logistic data=&data;
model &event (event='1') = &var;
run;
%end;
/* Append results to temporary table */
data _null_;
set _null_;
var_name = &var;
output;
run;
%end;
/* Output final results table */
proc print data=_null_;
run;
%mend;
%univariate_logistic(data=base, event=revasc6m, vars=age bmi ,
class_vars= sexc ethnicityc );
Hello @J_Park,
As a rule, a DATA step of the form
data _null_;
...
run;
does not create an output dataset. So, using _null_ later in a SET or PROC PRINT statement doesn't make sense as there is nothing to read.
Your non-macro code uses ODS OUTPUT statements. You can use them in your macro, too. Just insert
ods output OddsRatios(persist=proc) = odds;
ods output ParameterEstimates(persist=proc) = param;
at the beginning of the macro (after the %MACRO statement) and
ods output close;
at the end (before the %MEND statement). As a result, datasets ODDS and PARAM will contain the concatenated OddsRatios and ParameterEstimates outputs, respectively.
Also, consider using a %LOCAL statement in your macro (before the first %LET statement) to avoid unwanted side effects on macro variables outside of your macro:
%local has_class_vars i var;
Hi,
Thanks for providing the code. When you say "it didn't produce the summary", do you mean there was no output, or there was an issue in the log, or the output was incorrect, etc? Please clarify what you received vs what you want.
Please try adding the following macro diagnostic statement before you invoke the macro again and post the log using the Insert Code icon "</>":
options mprint symbolgen;
Thanks & kind regards,
Amir.
@J_Park wrote:
2836 %end;
ERROR: There is no matching %DO statement for the %END. This statement will be ignored.
So what %DO is this %END associated with? I don't see one, and SAS doesn't see one either
Your lack of output is explained by @FreelanceReinh above.
@J_Park wrote:
ERROR: There is no matching %DO statement for the %END. This statement will be ignored.
Delete the duplicate %END statement.
%end; %end;
The %END statement of the outer %DO-%END block is already there, further below. Proper code indentation will make this clearly visible.
@FreelanceReinh wrote:
@J_Park wrote:
ERROR: There is no matching %DO statement for the %END. This statement will be ignored.Delete the duplicate %END statement.
%end; %end;The %END statement of the outer %DO-%END block is already there, further below. Proper code indentation will make this clearly visible.
I don't think that's it
%let has_class_vars = %length(&class_vars); %if &has_class_vars > 0 %then %do; /* Run logistic regression for categorical variables */ %do i = 1 %to %sysfunc(countw(&class_vars)); %let var = %scan(&class_vars, &i); proc logistic data=&data; class &var / param=ref ref=last; model &event (event='1') = &var; run; %end; %end;
There are two %DO and %END in this part of the code. The green %DO matches the green %END and the red %DO matches the red %END.
Oh yes, you're right, of course. The extraneous %END to be deleted is the one "further below" (between the nonsensical steps which are to be deleted as well).
I got this message:
MPRINT(UNIVARIATE_LOGISTIC): data _null_;
MPRINT(UNIVARIATE_LOGISTIC): set _null_;
SYMBOLGEN: Macro variable VAR resolves to bmi
MPRINT(UNIVARIATE_LOGISTIC): var_name = bmi;
MPRINT(UNIVARIATE_LOGISTIC): output;
MPRINT(UNIVARIATE_LOGISTIC): run;
NOTE: Variable bmi is uninitialized.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MPRINT(UNIVARIATE_LOGISTIC): proc print data=_null_;
MPRINT(UNIVARIATE_LOGISTIC): run;
NOTE: No variables in data set WORK._NULL_.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
@J_Park wrote:
I got this message:
MPRINT(UNIVARIATE_LOGISTIC): data _null_;
MPRINT(UNIVARIATE_LOGISTIC): set _null_;
SYMBOLGEN: Macro variable VAR resolves to bmi
MPRINT(UNIVARIATE_LOGISTIC): var_name = bmi;
MPRINT(UNIVARIATE_LOGISTIC): output;
MPRINT(UNIVARIATE_LOGISTIC): run;NOTE: Variable bmi is uninitialized.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MPRINT(UNIVARIATE_LOGISTIC): proc print data=_null_;
MPRINT(UNIVARIATE_LOGISTIC): run;NOTE: No variables in data set WORK._NULL_.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
From now on, please provide logs in the "Insert Code" window (the </> icon), like this
MPRINT(UNIVARIATE_LOGISTIC): data _null_; MPRINT(UNIVARIATE_LOGISTIC): set _null_; SYMBOLGEN: Macro variable VAR resolves to bmi MPRINT(UNIVARIATE_LOGISTIC): var_name = bmi; MPRINT(UNIVARIATE_LOGISTIC): output; MPRINT(UNIVARIATE_LOGISTIC): run; NOTE: Variable bmi is uninitialized. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds MPRINT(UNIVARIATE_LOGISTIC): proc print data=_null_; MPRINT(UNIVARIATE_LOGISTIC): run; NOTE: No variables in data set WORK._NULL_. NOTE: PROCEDURE PRINT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds
So, this is telling you that the variable BMI does not have a value. Why? Because as stated above by @FreelanceReinh there is NO DATA in a data set named _NULL_. You have to give some other name to this data set in order for data to be saved and used later in the program.
Hello @J_Park,
As a rule, a DATA step of the form
data _null_;
...
run;
does not create an output dataset. So, using _null_ later in a SET or PROC PRINT statement doesn't make sense as there is nothing to read.
Your non-macro code uses ODS OUTPUT statements. You can use them in your macro, too. Just insert
ods output OddsRatios(persist=proc) = odds;
ods output ParameterEstimates(persist=proc) = param;
at the beginning of the macro (after the %MACRO statement) and
ods output close;
at the end (before the %MEND statement). As a result, datasets ODDS and PARAM will contain the concatenated OddsRatios and ParameterEstimates outputs, respectively.
Also, consider using a %LOCAL statement in your macro (before the first %LET statement) to avoid unwanted side effects on macro variables outside of your macro:
%local has_class_vars i var;
Hello FreelanceReinh!
Your suggestion worked!!!! Amazing! I spent the whole day to try to figure this out.
Thank you so much! I really appreciate your help.
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
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.
Ready to level-up your skills? Choose your own adventure.