I am looking to use a factor based on YRMON (YYYY:MM) from a static list of factors that are based on the last 12 months (rolling forward every month)
I have a static dataset that looks this simple (see below): I basically need to create a format that changes the yrmon to a rolling 13 months that I can stamp on the factor (for calculation needs) based on the yrmon.
yrmon facto
DATE00 1.00000
DATE01 0.99944
DATE02 0.99907
DATE03 0.99907
DATE04 0.99889
DATE05 0.99799
DATE06 0.99659
DATE07 0.99500
DATE08 0.99296
DATE09 0.99100
DATE10 0.85000
DATE11 0.78000
DATE12 0.34900
Example Data before/after:
YRMON PAYAMT PAYAMT_AFTER
2020:10 $100.00 $34.90
2020:08 $100.00 $85.00
Here's what I have so far:
/*Create macro dates*/
%let to_date = %sysfunc(date());
%let paydt = %sysfunc(intnx(month,&to_date, -(0)));
%let payday = %eval(&paydt. -1);
%let chirodt12 = %sysfunc(intnx(month,&payday,-0), date9.);
%let chirodt11 = %sysfunc(intnx(month,&payday,-1), date9.);
%let chirodt10 = %sysfunc(intnx(month,&payday,-2), date9.);
%let chirodt9 = %sysfunc(intnx(month,&payday,-3), date9.);
%let chirodt8 = %sysfunc(intnx(month,&payday,-4), date9.);
%let chirodt7 = %sysfunc(intnx(month,&payday,-5), date9.);
%let chirodt6 = %sysfunc(intnx(month,&payday,-6), date9.);
%let chirodt5 = %sysfunc(intnx(month,&payday,-7), date9.);
%let chirodt4 = %sysfunc(intnx(month,&payday,-8), date9.);
%let chirodt3 = %sysfunc(intnx(month,&payday,-9), date9.);
%let chirodt2 = %sysfunc(intnx(month,&payday,-10), date9.);
%let chirodt1 = %sysfunc(intnx(month,&payday,-11), date9.);
%let chirodt0 = %sysfunc(intnx(month,&payday,-12), date9.);
%put chirodt12 &chirodt12.;
%put chirodt11 &chirodt11.;
%put chirodt10 &chirodt10.;
%put chirodt9 &chirodt9.;
%put chirodt8 &chirodt8.;
%put chirodt7 &chirodt7.;
%put chirodt6 &chirodt6.;
%put chirodt5 &chirodt5.;
%put chirodt4 &chirodt4.;
%put chirodt3 &chirodt3.;
%put chirodt2 &chirodt2.;
%put chirodt1 &chirodt1.;
%put chirodt0 &chirodt0.;
filename ibnr "/path/to/file/file.txt";
data ibnr;
infile ibnr dlm='09'X dsd missover firstobs = 2;
informat month $6. factor 7.5;
input month factor;
run;
data ibnr;
set ibnr;
if month = 'DATE12' then yrmon = put("&chirodt12"D, yymmc7.);
else if month = 'DATE11' then yrmon = put("&chirodt11"D, yymmc7.);
else if month = 'DATE10' then yrmon = put("&chirodt10"D, yymmc7.);
else if month = 'DATE09' then yrmon = put("&chirodt9"D, yymmc7.);
else if month = 'DATE08' then yrmon = put("&chirodt8"D, yymmc7.);
else if month = 'DATE07' then yrmon = put("&chirodt7"D, yymmc7.);
else if month = 'DATE06' then yrmon = put("&chirodt6"D, yymmc7.);
else if month = 'DATE05' then yrmon = put("&chirodt5"D, yymmc7.);
else if month = 'DATE04' then yrmon = put("&chirodt4"D, yymmc7.);
else if month = 'DATE03' then yrmon = put("&chirodt3"D, yymmc7.);
else if month = 'DATE02' then yrmon = put("&chirodt2"D, yymmc7.);
else if month = 'DATE01' then yrmon = put("&chirodt1"D, yymmc7.);
else if month = 'DATE00' then yrmon = put("&chirodt0"D, yymmc7.);
run;
/*format for later use to stamp on factor for calculations*/
data chrofact (keep = fmtname label start type hlo);
retain fmtname 'chfact' type 'C';
set ibnr end = lastrec;
start=yrmon;
label = factor;
output;
if lastrec then do;
start='XXX' ;
hlo = 'O';
label = '0';
output;
end;
run;
proc format cntlin = chrofact;
run;
This gives me what I want; but I'm just sure there's a simpler method out there
Converting a text value to a SAS date value is an INPUT operation (i.e. INFORMAT), not a PUT operation (i.e. FORMAT).
Instead consider creating a lookup table that maps a literal string "DATE<nn>"
to a SAS date value corresponding to some predetermined base date.
Example
Decode the <nn>
portion of the string literal and apply it in a call to INTNX
. Use the output as the basis of CNTLIN for INFORMAT or as a lookup table LEFT JOINED or HASH JOINED to some other data set containing string literals "DATE"
data have;
length yrmon $6 facto 8.;
input yrmon facto;
basedate = today();
month = input(substr(yrmon,5),2.);
month_ago = 12-month;
ago_date = intnx('month', basedate, -month_ago);
format ago_date yymmdd10.;
datalines;
DATE00 1.00000
DATE01 0.99944
DATE02 0.99907
DATE03 0.99907
DATE04 0.99889
DATE05 0.99799
DATE06 0.99659
DATE07 0.99500
DATE08 0.99296
DATE09 0.99100
DATE10 0.85000
DATE11 0.78000
DATE12 0.34900
;
Image of output data set in viewer