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

Hello,

 

I am developing a macro program to use for two different analyses.  Below is a simplified version of the program.  The actual program is much larger.  I included a global macro variable "cohort" within the macro program.  As you see below, for the first execution of the program, the variable "cohort" was assigned a null value.  The entire program executed as desired for this step. 

 

%let cohort = ;

%macro frequencies(year,var);
proc freq data=cohort_flags(where=(eligible=1 & year=&year &cohort)) noprint;
	table &var / out=freq;
	by orsid;
run;
%mend;

*Example;
%frequencies(2012,race);

However, for the second analysis, I want to restrict incoming observations to those that have the same cohort allocation as a given year.  What I want is to assign a value to the global macro variable "cohort" that acts as an additional statement within the where option.  I know that the following is not valid syntax, but to communicate what I want, I would like the resolved macro variable to create code within the macro program that looks like this "and cohort = &year", with "year" calling the local macro variable.  I have been experimenting with different combinations of %nrstr and %nrquote, but have been unsuccessful thus far.  Below is an example of my last failed experiment.

 

%let cohort = %nrstr(and cohort = &year);
%let cohort = %nrstr(and cohort = %nrquote(%unquote(&year));

I keep getting the error message 

 

ERROR 22-322: Missing ')' parenthesis

 

I would greatly appreciate your help in creating a global macro variable that resolves within the macro program to reference the local macro variable "year".

 

Thanks,

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

So you want to get the value of COHORT to be the string:  

 

and cohort = &year

That is easy to do with a DATA step. 

data _null_;
  call symputx('cohort','and cohort = &year');
run;

Much harder to do with pure macro code.  Here is a trick that should work.

%let cohort=and cohort = &&%upcase(year);

The macro processor will evaluate && to &, but the use of the macro function around YEAR prevents the macro processor from then trying to resolve &YEAR.

 

 

View solution in original post

4 REPLIES 4
novinosrin
Tourmaline | Level 20

One more closing parenthesis &year)));

 

%let cohort = %nrstr(and cohort = %nrquote(%unquote(&year)));

 

LEINAARE
Obsidian | Level 7

Hi @novinosrin 

 

I added the extra parenthesis as you suggested.  Below is a copy of the log with the full macro in it.

 

9803 options mprint symbolgen mlogic;

9804 %macro frequencies(year,var,missing);
9805 %put Output frequencies of categories by ORSID;
9806 proc freq data=cohort_flags(where=(eligible=1 & year=&year &cohort)) noprint;
9807 table &var / out=freq;
9808 by orsid;
9809 run;
9810 %put Separate duplicates & ensure correct number of total enrollees for &year;
9811 proc sort data=freq nodupkey
9812 out=enrollee_count
9813 dupout=duplicates;
9814 by orsid;
9815 run;
9816 %put Ensure duplicate observations are not missing;
9817 data anymissing;
9818 set duplicates (where=(&var=&missing));
9819 run;
9820 %put Print frequency counts and missing observations;
9821 proc freq data=freq (drop=count percent);
9822 table &var;
9823 run;
9824 %mend;

9825 %let cohort = %nrstr(and cohort = %nrquote(%unquote(&year)));
9826 %frequencies(2012,new_race,.);
MLOGIC(FREQUENCIES): Beginning execution.
MLOGIC(FREQUENCIES): Parameter YEAR has value 2012
MLOGIC(FREQUENCIES): Parameter VAR has value new_race
MLOGIC(FREQUENCIES): Parameter MISSING has value .
MLOGIC(FREQUENCIES): %PUT Output frequencies of categories by ORSID
Output frequencies of categories by ORSID
SYMBOLGEN: Macro variable YEAR resolves to 2012
SYMBOLGEN: Macro variable COHORT resolves to and cohort = %nrquote(%unquote(&year))
SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been
unquoted for printing.
NOTE 137-205: Line generated by the invoked macro "FREQUENCIES".
1 proc freq data=cohort_flags(where=(eligible=1 & year=&year &cohort)) noprint; table &var
-
22
1 ! / out=freq; by orsid; run;
ERROR 22-322: Missing ')' parenthesis for data set option list

NOTE: Line generated by the invoked macro "FREQUENCIES".
1 proc freq data=cohort_flags(where=(eligible=1 & year=&year &cohort)) noprint; table &var
-
79
1 ! / out=freq; by orsid; run;
ERROR 79-322: Expecting a ).

NOTE: Line generated by the macro variable "COHORT".
1 and cohort = %nrquote(%unquote(&year))
-
22
-
76
ERROR: Syntax error while parsing WHERE clause.
MPRINT(FREQUENCIES): proc freq data=cohort_flags(where=(eligible=1 & year=2012 and cohort =
%nrquote(%unquote(&year)))) noprint;
SYMBOLGEN: Macro variable VAR resolves to new_race
MPRINT(FREQUENCIES): table new_race / out=freq;
MPRINT(FREQUENCIES): by orsid;
MPRINT(FREQUENCIES): run;

ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string,
a numeric constant, a datetime constant, a missing value, (, *, +, -, :, INPUT, NOT,
PUT, ^, ~.

ERROR 76-322: Syntax error, statement will be ignored.

NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.FREQ may be incomplete. When this step was stopped there were 0
observations and 0 variables.
WARNING: Data set WORK.FREQ was not replaced because this step was stopped.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.05 seconds
cpu time 0.04 seconds

MLOGIC(FREQUENCIES): %PUT Separate duplicates & ensure correct number of total enrollees for &year
SYMBOLGEN: Macro variable YEAR resolves to 2012
Separate duplicates & ensure correct number of total enrollees for 2012


MPRINT(FREQUENCIES): proc sort data=freq nodupkey out=enrollee_count dupout=duplicates;
MPRINT(FREQUENCIES): by orsid;
ERROR: Variable ORSID not found.
MPRINT(FREQUENCIES): run;

NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.ENROLLEE_COUNT may be incomplete. When this step was stopped there were
0 observations and 0 variables.
WARNING: Data set WORK.ENROLLEE_COUNT was not replaced because this step was stopped.
WARNING: The data set WORK.DUPLICATES may be incomplete. When this step was stopped there were 0
observations and 0 variables.
WARNING: Data set WORK.DUPLICATES was not replaced because this step was stopped.
NOTE: PROCEDURE SORT used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds

MLOGIC(FREQUENCIES): %PUT Ensure duplicate observations are not missing
Ensure duplicate observations are not missing


MPRINT(FREQUENCIES): data anymissing;
SYMBOLGEN: Macro variable VAR resolves to new_race
SYMBOLGEN: Macro variable MISSING resolves to .
MPRINT(FREQUENCIES): set duplicates (where=(new_race=.));
ERROR: Variable new_race is not on file WORK.DUPLICATES.
MPRINT(FREQUENCIES): run;

NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.ANYMISSING may be incomplete. When this step was stopped there were 0
observations and 0 variables.
WARNING: Data set WORK.ANYMISSING was not replaced because this step was stopped.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds


MLOGIC(FREQUENCIES): %PUT Print frequency counts and missing observations
Print frequency counts and missing observations
MPRINT(FREQUENCIES): proc freq data=freq (drop=count percent);
ERROR: The variable count in the DROP, KEEP, or RENAME list has never been referenced.
ERROR: The variable percent in the DROP, KEEP, or RENAME list has never been referenced.
SYMBOLGEN: Macro variable VAR resolves to new_race
MPRINT(FREQUENCIES): table new_race;
ERROR: No data set open to look up variables.
MPRINT(FREQUENCIES): run;

NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds

MLOGIC(FREQUENCIES): Ending execution.

Tom
Super User Tom
Super User

So you want to get the value of COHORT to be the string:  

 

and cohort = &year

That is easy to do with a DATA step. 

data _null_;
  call symputx('cohort','and cohort = &year');
run;

Much harder to do with pure macro code.  Here is a trick that should work.

%let cohort=and cohort = &&%upcase(year);

The macro processor will evaluate && to &, but the use of the macro function around YEAR prevents the macro processor from then trying to resolve &YEAR.

 

 

LEINAARE
Obsidian | Level 7

Hi @Tom,

 

Thank you for your help.  I used the macro code you provided, and it worked well. 

 

Thanks,

 

Ted

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 4 replies
  • 1060 views
  • 0 likes
  • 3 in conversation