BookmarkSubscribeRSS Feed
reubendon
Calcite | Level 5
Data description: Dataset called pop has the char variable ID, and the numeric date variable DT_INDEX. It also has 12 numeric date variables called pre_date01 to pre_date12, which correspond to the date 1,2,...12 months prior to DT_INDEX. 
 
What I am trying to do: Use a macro to loop through the pre_date variables 01 to 12. For every pre_date variable, I want to set a macro variable (called &mo) to the month value associated with the pre_date variables. So for example, if pre_date01 is 20180620, then I want &mo to be 06 for that iteration of the loop.
 
The line giving me trouble:  %let mo = %sysfunc(month(pre_date&mo_before));
The error message: ERROR: Argument 1 to function MONTH referenced by the %SYSFUNC or %QSYSFUNC macro function is not a number.
 
The chunk of relevant code is below and I have bolded the problem line.
 
%macro test;
data pop;
set pop;
         %do i = 01 %to 12;
        /* &mo_before is the amount of months before DT_INDEX */
         %let mo_before = %sysfunc(putn(&i, z2.));
 
         /* &mo is the actual month associated with the date 1,2,3,...12 months before DT_INDEX */
         %let mo = %sysfunc(month(pre_date&mo_before));
 
/* Rest of the code removed from sas support forum post */
%end;
run;
%mend;
%test;
 
 
8 REPLIES 8
PaigeMiller
Diamond | Level 26

Get out of the habit of working with dates as text strings. In SAS, dates should always be numbers, the integer number of days after 01JAN1960. SAS does not recognize 20180620 as a date, even if humans do recognize it as a date. It needs to be converted to an actual numeric SAS date value, and then and only then will the MONTH() function work. SAS has done all the necessary creating functions formats and informats to work with dates, so you don't have to struggle with these things.

 

Furthermore, there seems to be no need for a macro here, and no need for macro variables or SYSFUNC either. You can use a DO loop in a SAS data step. Do not make programming more complicated than it has to be.

 

data pop;
/*set pop;*/ /* this is commented out because I don't have your data set */
    predate=20180620; /* This is not a SAS date, you have to convert it to a SAS date */ 
    predate1=input(put(predate,8.),yymmdd8.); /* Convert it to a SAS date, which is 21355 to SAS or to us humans it is 20JUN2018 */ 
    mo_before=month(predate1);
    format predate1 date9.;
run;

 

 

--
Paige Miller
reubendon
Calcite | Level 5

The dates were never text strings, they are dates in YYMMDDN. format. Converting to YYMMDD8. format did not work. And as far as I can tell, it does need to be a macro. I removed a block of code from this post to remove distractions from my issue at hand, but I need it to be a macro so that I can dynamically reference variables that end in the suffix of &mo (01 to 12).

 

The issue at hand is that I cannot set a macro variable to the numeric month from a sas date

PaigeMiller
Diamond | Level 26

@reubendon wrote:

The dates were never text strings, they are dates in YYMMDDN. format.

The issue at hand is that I cannot set a macro variable to the numeric month from a sas date


Okay, please clarify. Are the date value stored in numeric variables according to PROC CONTENTS (or similar), and the format is YYMMDDN. ? Or are they really the value 20180620? Show us the PROC CONTENTS output for this variable.


With regards to your macro statements, please explain further ... and in detail ... the values 01 to 12 can all be handled in a DATA step loop with an ARRAY. In addition, %SYSFUNC cannot access values in a SAS data set variable, like the variable you have named PRE_DATE01 PRE_DATE02 ... 

--
Paige Miller
reubendon
Calcite | Level 5

Proc contents output:

135136137138139140141142143144145146

pre_date01Num8YYMMDD8. 
pre_date02Num8YYMMDD8. 
pre_date03Num8YYMMDD8. 
pre_date04Num8YYMMDD8. 
pre_date05Num8YYMMDD8. 
pre_date06Num8YYMMDD8. 
pre_date07Num8YYMMDD8. 
pre_date08Num8YYMMDD8. 
pre_date09Num8YYMMDD8. 
pre_date10Num8YYMMDD8. 
pre_date11Num8YYMMDD8. 
pre_date12Num8YYMMDD8.

 

entire code:

                 
%macro test;

data pop;
	set pop;
	
	%do i = 01 %to 12;
		/*	&mo_before is the amount of months before DT_INDEX	*/
		%let mo_before = %sysfunc(putn(&i, z2.));
		
		/*	&mo is the actual month associated with the date 1,2,3,...12 months before DT_INDEX	*/
		%let mo = %sysfunc(month(pre_date&mo_before)); 

		/*	If the row's year matches the date 1,2,...months before DT_INDEX	*/
		if year(pre_date&mo_before) = REF_YR then do;
			/*	If the CST_SHR_GRP_CD_ variable corresponding to date&mo_before's month is 
			between "01" and "08" 	*/
			if  "01" <= CST_SHR_GRP_CD_&mo <= "08" 
				/*	Then LIS_PRE_ corresponding to 1,2,3,...12 months before is 1	*/
				then LIS_PRE_&mo_before = 1;
			else LIS_PRE_&mo = 0;
		end;
	%end;
run;
		
%mend;
%test;
 
PaigeMiller
Diamond | Level 26
data pop1; /* Very important, do not overwrite existing data sets */
    set pop;
    array p pre_date01-pre_date12;	
    do i = 1 to 12;
		/*	&mo_before is the amount of months before DT_INDEX	*/
		/* mo_before = i; */       /* Not needed, I think */
		mo = month(p(i)); 
     end;
run;

 

I think there's still something I don't understand about what you are doing, but the above should get you going in the right direction. Also the variable MO isn't really stored in each iteration, I suspect you want that but your actual code doesn't store it either.

--
Paige Miller
Kurt_Bremser
Super User

The text "predate01" is clearly not a number, and also not a macro variable reference which could resolve to a number.

You cannot access a data step variable in macro language like this; the macro preprocessor works before code is even sent to the data step compiler.

To loop through a set of data step variables, define an array for them and use a data step DO loop.

reubendon
Calcite | Level 5

Sure but even this still gives me an issue:

 

%let 

m = month(pre_date&mo_before); /* This line works fine*/
%let mo_before = %sysfunc(putn(m, z2.)); /*This line does does*/

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 8 replies
  • 838 views
  • 0 likes
  • 3 in conversation