SAS Macros

Reply
Contributor
Posts: 22

SAS Macros

Hello All,

 

I am using the following Macro code:

 

%MACRO rollingreg
(data=mom12.developing, out_ds=results,
id=country, date=date,
model_equation= RETURN = MOM,
start_date= 12-31-1996, end_date= 12-31-2014,
freq=month, s=1, n=36,
regprint=noprint);

%* Start with empty output data sets;
proc datasets nolist;
delete _all_ds _outest_ds;
run;

* Prepare input data for by-id-date use;
proc sort data=&data;
by &id &date;
run;

%* Set the 'by-id' variable;
%if &year_date=1 %then %let freq=year;
%* year frequency case;
%put Date variable: &date year_date: &year_date;
%put Start and end dates: &start_date &end_date // &sdate1 &sdate2;
%if &year_date=0 %then
%put %sysfunc(putn(&sdate1,date9.)) %sysfunc(putn(&sdate2,date9.));
%put Freq: &freq s: &s n: &n;

%* Preliminary date setting for each iteration/loop;
%* First end date (idate2) is n periods after the start date;
%if &year_date=1 %then %let idate2= %eval(&sdate1+(&n-1));
%else %let idate2= %sysfunc(intnx(&freq,&sdate1,(&n-1),end));
%if &year_date=0 %then %let idate1= %sysfunc(intnx(&freq,&idate2,-&n+1,begin));
%else %let idate1= %eval(&idate2-&n+1);
%put First loop: &idate1 -- &idate2;
%put Loop through: &sdate2;
%if (&idate2 > &sdate2) %then %do;

%* Dates are not acceptable-- show problem, do not run loop;
%put PROBLEM-- end date for loop exceeds range : ( &idate2 > &sdate2 );
%end;
%else %do; *Dates are accepted-- run loops;
%let jj=0;
%do %while(&idate2 <= &sdate2);
%let jj=%eval(&jj+1);

%*Define loop start date (idate1) based on inherited end date (idate2);
%if &year_date=0 %then %do;
%let idate1= %sysfunc(intnx(&freq,&idate2,-&n+1,begin));
%let date1c= %sysfunc(putn(&idate1,date9.));
%let date2c= %sysfunc(putn(&idate2,date9.));
%end;
%if &year_date=1 %then %do;
%let idate1= %eval(&idate2-&n+1);
%let date1c= &idate1;
%let date2c= &idate2;
%end;
%let idate1= %sysfunc(max(&sdate1,&idate1));
%put Loop: &jj -- &date1c &date2c;
%put &jj -- &idate1 &idate2;
proc datasets nolist;
delete _outest_ds;
run;

%***** analysis code here -- for each loop;
%* noprint to just make output set;
%let noprint= noprint;
%if %upcase(®print) = yes | %upcase(®print) = print %then %let noprint= ;
proc reg data=&data
outest=_outest_ds edf
&noprint;
where &date between &idate1 and &idate2;
model &model_equation;
&by_id;
run;

%* Add loop date range variables to output set;
data _outest_ds;
set _outest_ds;
regobs= _p_ + _edf_; %* number of observations in regression;
date1= &idate1;
date2= &idate2;
%if &year_date=0 %then format date1 date2 date9.;
run;
%* Append results;
proc datasets nolist;
append base=_all_ds data=_outest_ds;
run;

%* Set next loop end date;
%if &year_date=0 %then %let idate2= %sysfunc(intnx(&freq,&idate2,&s,end));
%else %if &year_date=1 %then %let idate2= %eval(&idate2+&s);
%end; *% end of loop;
%* Save outout set to desired location;
data &out_ds;
set _all_ds;
run;
proc sort data=&out_ds;
by &id date2;
run;
%end; %* end for date check pass section;
%mend;
%rollingreg;

 

 

However, whenever I run the above code, I see the following error message:

WARNING: Apparent symbolic reference YEAR_DATE not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: &year_date=1
ERROR: The macro ROLLINGREG will stop executing.

SAS Super FREQ
Posts: 472

Re: SAS Macros

This is the first place that macro variable appears.

%if &year_date=1 %then %let freq=year;

It has not been set to a value before you used it.

 

Your code would be easier to look at if you use the insert SAS code "run box" when you paste it.

Super User
Posts: 21,530

Re: SAS Macros

Posted in reply to WarrenKuhfeld

Format the code so it's legible as well. The indents help you find errors and a wall of code is difficult to parse.

 

%MACRO rollingreg
			(data=mom12.developing, out_ds=results,
			id=country, date=date,
			model_equation= RETURN = MOM,
			start_date= 12-31-1996, end_date= 12-31-2014,
			freq=month, s=1, n=36,
			regprint=noprint);
	%* Start with empty output data sets;
	proc datasets nolist;
		delete _all_ds _outest_ds;
	run;

	* Prepare input data for by-id-date use;
	proc sort data=&data;
		by &id &date;
	run;

	%* Set the 'by-id' variable;
	%if &year_date=1 %then
		%let freq=year;

	%* year frequency case;
	%put Date variable: &date year_date: &year_date;
	%put Start and end dates: &start_date &end_date // &sdate1 &sdate2;

	%if &year_date=0 %then
		%put %sysfunc(putn(&sdate1,date9.)) %sysfunc(putn(&sdate2,date9.));
	%put Freq: &freq s: &s n: &n;

	%* Preliminary date setting for each iteration/loop;
	%* First end date (idate2) is n periods after the start date;
	%if &year_date=1 %then
		%let idate2= %eval(&sdate1+(&n-1));
	%else %let idate2= %sysfunc(intnx(&freq,&sdate1,(&n-1),end));

	%if &year_date=0 %then
		%let idate1= %sysfunc(intnx(&freq,&idate2,-&n+1,begin));
	%else %let idate1= %eval(&idate2-&n+1);
	%put First loop: &idate1 -- &idate2;
	%put Loop through: &sdate2;

	%if (&idate2 > &sdate2) %then
		%do;
			%* Dates are not acceptable-- show problem, do not run loop;
			%put PROBLEM-- end date for loop exceeds range : ( &idate2 > &sdate2 );
		%end;
	%else
		%do;
			*Dates are accepted-- run loops;
			%let jj=0;

			%do %while(&idate2 <= &sdate2);
				%let jj=%eval(&jj+1);

				%*Define loop start date (idate1) based on inherited end date (idate2);
				%if &year_date=0 %then
					%do;
						%let idate1= %sysfunc(intnx(&freq,&idate2,-&n+1,begin));
						%let date1c= %sysfunc(putn(&idate1,date9.));
						%let date2c= %sysfunc(putn(&idate2,date9.));
					%end;

				%if &year_date=1 %then
					%do;
						%let idate1= %eval(&idate2-&n+1);
						%let date1c= &idate1;
						%let date2c= &idate2;
					%end;

				%let idate1= %sysfunc(max(&sdate1,&idate1));
				%put Loop: &jj -- &date1c &date2c;
				%put &jj -- &idate1 &idate2;

				proc datasets nolist;
					delete _outest_ds;
				run;

				%***** analysis code here -- for each loop;
				%* noprint to just make output set;
				%let noprint= noprint;

				%if %upcase(®print) = yes | %upcase(®print) = print %then
					%let noprint=;

				proc reg data=&data
					outest=_outest_ds edf
					&noprint;
					where &date between &idate1 and &idate2;
					model &model_equation;
					&by_id;
				run;

				%* Add loop date range variables to output set;
				data _outest_ds;
					set _outest_ds;
					regobs= _p_ + _edf_;

					%* number of observations in regression;
					date1= &idate1;
					date2= &idate2;

					%if &year_date=0 %then
						format date1 date2 date9.;
				run;

				%* Append results;
				proc datasets nolist;
					append base=_all_ds data=_outest_ds;
				run;

				%* Set next loop end date;
				%if &year_date=0 %then
					%let idate2= %sysfunc(intnx(&freq,&idate2,&s,end));
				%else %if &year_date=1 %then
					%let idate2= %eval(&idate2+&s);
			%end;

			*% end of loop;
			%* Save outout set to desired location;
			data &out_ds;
				set _all_ds;
			run;

			proc sort data=&out_ds;
				by &id date2;
			run;

		%end;

	%* end for date check pass section;
%mend;

%rollingreg;
Super User
Posts: 21,530

Re: SAS Macros

Where are &sdate1 and &sdate2 defined?

 

There looks to be a bunch of logical errors here. Those are just the ones I first saw.

Contributor
Posts: 22

Re: SAS Macros

Posted in reply to WarrenKuhfeld

Thanks for your help. Yes, you are correct. The macro variable year_date has not been set to a value before you used it.

 

The year_date macro variable is used in the code ONLY IF I am using annual data. However, I am using monthly data not annual data, so how I can adjust the code for monthly data?

Ask a Question
Discussion stats
  • 4 replies
  • 157 views
  • 0 likes
  • 3 in conversation